Describe the bug
Lazygit can write a generated state.yml that it cannot read back on the next launch when a cached GitHub pull request title begins with a newline.
Startup then fails before the UI opens with an error like:
yaml: line 79: did not find expected key
The invalid state was in the generated GitHub PR cache under githubPullRequests:
githubPullRequests:
/path/to/repo:
- headRefName: example-branch
number: 9
title: |4-
Example pull request title
state: MERGED
url: https://github.com/example/example/pull/9
headRepositoryOwner: example
Removing ~/.local/state/lazygit/state.yml lets lazygit start again, but the problem can recur if the cache is written with the same title shape.
To Reproduce
This reproduces with the same gopkg.in/yaml.v3 marshal/unmarshal path used for app state:
package main
import (
"fmt"
"gopkg.in/yaml.v3"
)
type State struct {
GithubPullRequests map[string][]PR `yaml:"githubPullRequests"`
}
type PR struct {
HeadRefName string `yaml:"headRefName"`
Number int `yaml:"number"`
Title string `yaml:"title"`
State string `yaml:"state"`
}
func main() {
state := State{GithubPullRequests: map[string][]PR{
"/tmp/repo": {{
HeadRefName: "example-branch",
Number: 9,
Title: "\nExample pull request title",
State: "MERGED",
}},
}}
b, err := yaml.Marshal(state)
fmt.Println(err)
fmt.Print(string(b))
var out State
fmt.Println(yaml.Unmarshal(b, &out))
}
Output:
<nil>
githubPullRequests:
/tmp/repo:
- headRefName: example-branch
number: 9
title: |4-
Example pull request title
state: MERGED
yaml: line 2: did not find expected key
I also reproduced this against current master with a small regression test that:
- Creates an
AppState with a CachedPullRequest.Title beginning with \n.
- Marshals it with
yaml.Marshal.
- Unmarshals it back into
AppState.
The unmarshal fails.
Expected behavior
Lazygit should not persist generated app state that prevents the next launch.
A possible fix is to normalize cached PR titles before app state serialization, or otherwise avoid the yaml.v3 leading-newline block scalar output for this field.
Version info
commit=v0.61.1, build date=2026-04-13T21:15:08Z, build source=binaryRelease, version=0.61.1, os=linux, arch=amd64, git version=2.54.0
I also checked current latest release, which is v0.61.1.
Terminal info
Linux shell/tmux environment.
This does not appear to be terminal-rendering related; startup fails while parsing state.yml.
Additional context
The path involved appears to be:
pkg/gui/controllers/helpers/refresh_helper.go copies pr.Title into config.CachedPullRequest.Title
pkg/config/app_config.go writes AppState using yaml.Marshal(c.appState)
- the next launch reads that file using
yaml.Unmarshal(appStateBytes, appState)
I tested one small local patch that made the regression test pass:
func (c CachedPullRequest) MarshalYAML() (interface{}, error) {
type cachedPullRequest CachedPullRequest
result := cachedPullRequest(c)
result.Title = strings.TrimLeft(result.Title, "\r\n")
return result, nil
}
That may not be the preferred upstream fix, but it prevents this specific cache field from making state.yml unreadable.
I saw the current contributing note about opening an issue before proposing a PR. Happy to provide the regression test/patch if useful.
Describe the bug
Lazygit can write a generated
state.ymlthat it cannot read back on the next launch when a cached GitHub pull request title begins with a newline.Startup then fails before the UI opens with an error like:
The invalid state was in the generated GitHub PR cache under
githubPullRequests:Removing
~/.local/state/lazygit/state.ymllets lazygit start again, but the problem can recur if the cache is written with the same title shape.To Reproduce
This reproduces with the same
gopkg.in/yaml.v3marshal/unmarshal path used for app state:Output:
I also reproduced this against current
masterwith a small regression test that:AppStatewith aCachedPullRequest.Titlebeginning with\n.yaml.Marshal.AppState.The unmarshal fails.
Expected behavior
Lazygit should not persist generated app state that prevents the next launch.
A possible fix is to normalize cached PR titles before app state serialization, or otherwise avoid the
yaml.v3leading-newline block scalar output for this field.Version info
I also checked current latest release, which is
v0.61.1.Terminal info
Linux shell/tmux environment.
This does not appear to be terminal-rendering related; startup fails while parsing
state.yml.Additional context
The path involved appears to be:
pkg/gui/controllers/helpers/refresh_helper.gocopiespr.Titleintoconfig.CachedPullRequest.Titlepkg/config/app_config.gowritesAppStateusingyaml.Marshal(c.appState)yaml.Unmarshal(appStateBytes, appState)I tested one small local patch that made the regression test pass:
That may not be the preferred upstream fix, but it prevents this specific cache field from making
state.ymlunreadable.I saw the current contributing note about opening an issue before proposing a PR. Happy to provide the regression test/patch if useful.