Visitar URL original
Repeatedly hitting index.lock failures · Issue #5906 · jesseduffield/lazygit · GitHub
Skip to content

Repeatedly hitting index.lock failures #5906

Open

Description

@edhgoose

Describe the bug

I am operating in a very large repo, and frequently hit problems where I can't check out a branch without getting the below error:

Image

fatal: Unable to create '/.git/index.lock': File exists.
Another git process seems to be running in this repository, or the lock file may be stale.

To Reproduce

I'm not sure how to reproduce directly, but for me it's as simple as switching branches will trigger it most of the time.

Expected behavior

I'd expect to rarely/never hit this index.lock problem.

Version info:

commit=, build date=, build source=Homebrew, version=0.64.0, os=darwin, arch=arm64, git version=2.55.0

Was also occurring on last two releases as well. I wonder if this is related: #5788?

Terminal info:

iTerm 2: version 3.6.11

Additional context

I'm running Goland at the same time, but I'm not using their Git features explicitly. I don't see anything that suggests it's Goland trying to read the git index.

I've tried to check what commands are holding the lock. I see git status --untracked-files=all --porcelain -z --find-renames=50% comes up a bit, and the parent is lazygit.

I tried running this manually to see how long it takes and got:

0.35s user 2.37s system 79% cpu 3.441 total

On avg it was somewhere between 2-4 seconds for this repo.

I see the following logs:

Logs

Aug 7 18:50:47 |DEBU| RunCommand command="git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium refs/heads/master --"
Aug 7 18:50:47 |INFO| postRefreshUpdate for localBranches took 253.042µs
Aug 7 18:50:47 |ERRO| read |0: file already closed
Aug 7 18:50:48 |DEBU| RunCommand command="git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium refs/heads/my-new-branch --"
Aug 7 18:50:48 |ERRO| read |0: file already closed
Aug 7 18:50:48 |DEBU| RunCommand command="git checkout my-new-branch"
Aug 7 18:50:48 |ERRO| fatal: Unable to create '/MyDirectory/.git/index.lock': File exists.

Another git process seems to be running in this repository, or the lock file may be stale

Aug 7 18:50:48 |INFO| git checkout my-new-branch (wall 101.912041ms, cpu 35.673ms)
Aug 7 18:50:48 |WARN| lock error prevented command from running; retrying in 20ms
Aug 7 18:50:48 |DEBU| RunCommand command="git checkout my-new-branch"
Aug 7 18:50:48 |ERRO| fatal: Unable to create '/MyDirectory/.git/index.lock': File exists.

Another git process seems to be running in this repository, or the lock file may be stale

Aug 7 18:50:48 |INFO| git checkout my-new-branch (wall 108.728791ms, cpu 30.895ms)
Aug 7 18:50:48 |WARN| lock error prevented command from running; retrying in 40ms
Aug 7 18:50:48 |DEBU| RunCommand command="git checkout my-new-branch"
Aug 7 18:50:48 |ERRO| fatal: Unable to create '/MyDirectory/.git/index.lock': File exists.

Another git process seems to be running in this repository, or the lock file may be stale

Aug 7 18:50:48 |INFO| git checkout my-new-branch (wall 111.455459ms, cpu 33.685ms)
Aug 7 18:50:48 |WARN| lock error prevented command from running; retrying in 80ms
Aug 7 18:50:48 |DEBU| RunCommand command="git checkout my-new-branch"
Aug 7 18:50:49 |ERRO| fatal: Unable to create '/MyDirectory/.git/index.lock': File exists.

Another git process seems to be running in this repository, or the lock file may be stale

Aug 7 18:50:49 |INFO| git checkout my-new-branch (wall 102.784125ms, cpu 34.459ms)
Aug 7 18:50:49 |WARN| lock error prevented command from running; retrying in 160ms
Aug 7 18:50:49 |DEBU| RunCommand command="git checkout my-new-branch"
Aug 7 18:50:49 |ERRO| fatal: Unable to create '/MyDirectory/.git/index.lock': File exists.

Another git process seems to be running in this repository, or the lock file may be stale

Aug 7 18:50:49 |INFO| git checkout my-new-branch (wall 109.252791ms, cpu 32.028ms)
Aug 7 18:50:49 |WARN| lock error prevented command from running; retrying in 320ms
Aug 7 18:50:49 |DEBU| RunCommand command="git checkout my-new-branch"
Aug 7 18:50:49 |ERRO| fatal: Unable to create '/MyDirectory/.git/index.lock': File exists.

Another git process seems to be running in this repository, or the lock file may be stale

Aug 7 18:50:49 |INFO| git checkout my-new-branch (wall 106.687583ms, cpu 34.246ms)
Aug 7 18:50:49 |WARN| lock error prevented command from running; retrying in 640ms
Aug 7 18:50:50 |DEBU| RunCommand command="git checkout my-new-branch"
Aug 7 18:50:50 |ERRO| fatal: Unable to create '/MyDirectory/.git/index.lock': File exists.

Another git process seems to be running in this repository, or the lock file may be stale

Aug 7 18:50:50 |INFO| git checkout my-new-branch (wall 107.590709ms, cpu 35.349ms)
Aug 7 18:50:50 |INFO| refreshing all scopes (async)
Aug 7 18:50:50 |DEBU| RunCommand command="git for-each-ref "--format=%(objectname) %(refname)" refs/heads"
Aug 7 18:50:50 |INFO| git for-each-ref "--format=%(objectname) %(refname)" refs/heads (wall 33.102333ms, cpu 5.835ms)
Aug 7 18:50:50 |INFO| RefsSnapshot took 33.274375ms
Aug 7 18:50:50 |INFO| refreshed merge conflicts in 40.125µs

Activity

  1. dariogliendo commented on Aug 27, 2026

    @dariogliendo

    Same happening for me in a large repo. I get this message in almost every single command I try to run. In my case I think it's related with using the "nvim-fugitive" plugin for neovim, which I suspect is very active with git stuff as lazygit is. I have not checked fugitive's codebase tho, so I'm just guessing.

  2. edhgoose commented on Aug 29, 2026

    @edhgoose
    Author

    As per #5981 - I think this should resolve the issue:

    git config --global status.showUntrackedFiles normal (Globally)
    git config status.showUntrackedFiles normal (for this specific repo)

    The raised PR hopefully fixes it for everyone 🤞

  3. stefanhaller commented on Aug 31, 2026

    @stefanhaller
    Collaborator

    @edhgoose This doesn't make sense to me, for two reasons:

    • It only happens to work in your particular scenario because for your repo the time for git status --untracked-files=all happens to be above the retry threshold, but git status --untracked-files=normal happens to be below it. That is not necessarily true for other repos; I made an extremely huge one for testing, where =all takes ~15s and =normal takes ~10s, so in that repo your fix doesn't help.
    • The user experience is unacceptable. If you create a new directory with a new file in it, how would you stage that? It would require some new feature where you can override the =normal on demand so that you see the new file (a bit like typing git add newdir/newfile manually). I don't want to invest in adding such functionality. Or it would have to be opt-in for users who know they will never need to add new files to their repo; but that opt-in already exists, it's the git config.

    What we should do next is find out if it is lazygit itself that causes the error for you guys, or some other app running in the background.

    1. Lazygit itself: with the huge test repo mentioned above I can easily reproduce the error by not waiting long enough. When I focus the lazygit terminal window it makes a refresh involving a git status call, and if I don't wait those 10s (or 15s depending on the config), the next lazygit command like staging a file shows the error. The same happens when performing a lazygit command (e.g. press space to stage a file) and then not waiting long enough before performing the next one. Please try (both of you) if you can still reproduce the error when waiting long enough after bringing lazygit to the front, and between actions.
    2. Other programs: I'm just guessing here, but I can imagine git clients that use a file watcher to get notified of when they need to refresh their UI (Sublime Merge is an example of that), and then make git status calls without GIT_OPTIONAL_LOCKS=0. If they manage to start that call before lazygit makes its own post-command refresh, and that status takes longer than lazygit's ~1.2s retry interval, then this would totally explain the error. So if you are running git clients that you suspect could play a role here (e.g. fugitive or Goland), try quitting them and see if you can still reproduce the error.

    As for possible solutions: of course 1. is unacceptable, users shouldn't have to wait between commands to avoid errors. A simple improvement could be to simply increase the retry interval; bailing out on an index.lock that is genuinely stale (e.g. after a git process crashed) is a one-time thing where users have to delete the file, and I'd say it doesn't matter too much if that error appears after 1s or 5s. A more thorough solution could be for lazygit to track its own foreground status calls (after a focus-in or after a command), and wait for them instead of handling these through the normal retry loop heuristic. That requires a little more code, but may well be worth it.

    For 2.: if we do indeed find one that is responsible, the only thing to do there is to report an issue to them to suggest adding GIT_OPTIONAL_LOCKS=0 (or --no-optional-locks) to their background status calls. Nothing we can do on our side to fix that, except for increasing the retry threshold.

  4. edhgoose commented on Sep 13, 2026

    @edhgoose
    Author

    Hi @stefanhaller - thanks for your detailed reply. Sorry for the very slow response - I've not had time to focus on this issue.

    Regarding your questions:

    • No, I do not experience the problem if I wait. If I ensure the UI has updated to show my action is completed before attempting another action, then I do not trigger the index lock. If I try and rapid fire add multiple files, then I do experience the issue.
    • I experience the locking problem without any other git tools (my primary tool is Goland) running. I do have Sublime installed, but not with Sublime Merge. My research shows no other git processes running, except for the git fsmonitor--daemon.

    With your large repo - do you have the setting feature.manyFiles turned on? I've realised that's automatically turned on for me at my workplace, which in turn activates the core.untrackedCache. I think the key difference I'm seeing between the --untracked-files=all and --untracked-files=normal is that all can't / doesn't use the untrackedCache, which is why the performance difference is so stark. It's sub second for normal and multi-second for all.

    I've turned these settings (feature.manyFiles and core.untrackedCache) off, as well as the suggested showUntrackedFiles normal change recommended from the comment above, and removed the cache index:

    git config set core.untrackedCache false
    git config set feature.manyFiles false
    git config unset status.showUntrackedFiles
    
    # Ensuring the cache is removed:
    git update-index --no-untracked-cache
    
    time git status --untracked-files=normal --porcelain -z --find-renames=50%
    0.38s user 1.69s system 89% cpu 2.312 total
    
    time git status --untracked-files=all --porcelain -z --find-renames=50%
    0.39s user 1.62s system 108% cpu 1.856 total
    

    You can see the timing is pretty similar.

    Then turning the untrackedCache back on to confirm the difference is stark again:

    git config set core.untrackedCache true
    
    # Populate the cache:
    time git status --untracked-files=normal --porcelain -z --find-renames=50%
    0.44s user 1.83s system 106% cpu 2.133 total
    
    time git status --untracked-files=normal --porcelain -z --find-renames=50%
    0.20s user 0.25s system 119% cpu 0.376 total
    

    The time taken is significantly lower for normal.

    And now with all:

    time git status --untracked-files=all --porcelain -z --find-renames=50%  
    0.38s user 1.71s system 107% cpu 1.938 total
    
    # Again to prove it's not just a cache warmup problem:
    time git status --untracked-files=all --porcelain -z --find-renames=50%
    0.39s user 1.67s system 107% cpu 1.916 total
    

    Regarding your suggestion for lazygit to wait for its other commands to finish, I think the challenge with that is that the experience for the user could still be very poor if the UI doesn't allow interaction or update between those actions. i.e. at the moment if you undertake several actions (e.g. adding multiple files), the UI hangs while the actions block waiting for the command to retry.

    I wonder if instead of the feature changes, a better solution would be some documentation on recommended git settings for working with large repos? Which I think is to turn on these settings in git:

    Well documented elsewhere on using large repos:

    git config feature.manyFiles true
    

    Override the default lazygit behaviour for untracked-files all, which has the downside of a poor UX for adding new directories as shown below but should otherwise improve performance:

    git config status.showUntrackedFiles normal
    

    I don't perceive the UX to be too poor - it only affects files added to new directories:

    This is the default behaviour with all:
    Image

    This is the behaviour with showUntrackedFiles normal:

    The files within the new directory don't show (but the file within the existing directory does):
    Image

    And when you add the directory, the files show:
    Image

    There's obviously a downside if you don't wish to add the whole folder - but I don't personally mind. May be up to personal opinion!

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions