Skip to content

Exit cleanly when worktree/repository is removed while lazygit is running#5355

Open
ruudk wants to merge 1 commit intojesseduffield:masterfrom
ruudk:no-panic-on-worktree-removal
Open

Exit cleanly when worktree/repository is removed while lazygit is running#5355
ruudk wants to merge 1 commit intojesseduffield:masterfrom
ruudk:no-panic-on-worktree-removal

Conversation

@ruudk
Copy link
Contributor

@ruudk ruudk commented Mar 10, 2026

PR Description

Please check if the PR fulfills these requirements

  • Cheatsheets are up-to-date (run go generate ./...)
  • Code has been formatted (see here)
  • Tests have been added/updated (see here for the integration test guide)
  • Text is internationalised (see here)
  • If a new UserConfig entry was added, make sure it can be hot-reloaded (see here)
  • Docs have been updated if necessary
  • You've read through your own file changes for silly mistakes etc

When a worktree or repository is removed while lazygit is running, git commands fail with "fatal: not a git repository" or "fatal: Unable to read current working directory". Previously this caused a panic in BranchLoader.obtainBranches, crashing lazygit with a stack trace.

Changes:

  • BranchLoader.obtainBranches: return error instead of panic(err)
  • RefreshHelper.refreshBranches: wrap the error in ErrFatal and send it to the UI thread, causing the program to exit
  • PopupHandler.ErrorHandler: let ErrFatal bypass the popup handler so the error propagates to the main loop and triggers a clean exit
  • Add ErrFatal type to gui/types for errors that should terminate the program immediately
  • Add "fatal: Unable to read current working directory" to the known error mappings so it prints a friendly message on exit

Manual testing:

Terminal 1: cd "$(mktemp -d)" && mkdir test-repo && cd test-repo git init && git commit --allow-empty -m "init" git worktree add ../test-wt && cd ../test-wt
go build -o lazygit . && ./lazygit # (or path to built binary)

Terminal 2: rm -rf /path/to/test-wt /path/to/test-repo

Then press R in lazygit to refresh. It should exit with: "Error: the current working directory does not exist"

…ning

When a worktree or repository is removed while lazygit is running,
git commands fail with "fatal: not a git repository" or
"fatal: Unable to read current working directory". Previously this
caused a panic in BranchLoader.obtainBranches, crashing lazygit with
a stack trace.

Changes:

- BranchLoader.obtainBranches: return error instead of panic(err)
- RefreshHelper.refreshBranches: wrap the error in ErrFatal and send
  it to the UI thread, causing the program to exit
- PopupHandler.ErrorHandler: let ErrFatal bypass the popup handler
  so the error propagates to the main loop and triggers a clean exit
- Add ErrFatal type to gui/types for errors that should terminate
  the program immediately
- Add "fatal: Unable to read current working directory" to the known
  error mappings so it prints a friendly message on exit

Manual testing:

  Terminal 1:
    cd "$(mktemp -d)" && mkdir test-repo && cd test-repo
    git init && git commit --allow-empty -m "init"
    git worktree add ../test-wt && cd ../test-wt
    go build -o lazygit . && ./lazygit   # (or path to built binary)

  Terminal 2:
    rm -rf /path/to/test-wt /path/to/test-repo

  Then press R in lazygit to refresh. It should exit with:
    "Error: the current working directory does not exist"
@CJHwong
Copy link

CJHwong commented Mar 13, 2026

I ran into this as well. I was running lazygit inside a Claude Code worktree that got cleaned up when the session ended, which triggered the same panic in obtainBranches.

I took a different approach: instead of exiting, I detect the missing CWD at the top of Refresh and switch back to the main worktree automatically. The user keeps their session instead of getting dropped. If the main worktree itself is gone, it still panics since there's nowhere to recover to.

One thing worth noting: on macOS, os.Stat(".") succeeds on a deleted directory because the kernel holds the inode. You have to stat the absolute path from os.Getwd() instead. On Linux, os.Getwd() itself fails, so both cases need handling.

PR with code and integration test: #5367

@ruudk
Copy link
Contributor Author

ruudk commented Mar 13, 2026

I took a different approach: instead of exiting, I detect the missing CWD at the top of Refresh and switch back to the main worktree automatically. The user keeps their session instead of getting dropped. If the main worktree itself is gone, it still panics since there's nowhere to recover to.

That's also a possibility. But in that case, I think you should add a prompt that informs the user that this happened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants