Provide a detailed description of the proposed feature
Verification
TL;DR: the current update-lock error can be wrong for this case. Homebrew says another brew update process is running, but the lock holder was actually a detached git fsmonitor--daemon process from a Homebrew tap checkout. The message also does not expose enough information to understand why it is wrong or how to diagnose the real lock holder.
The crisp question is: if the update lock is held only by a detached git fsmonitor--daemon, is it safe for Homebrew to ignore that lock holder, or should Homebrew instead disable/stop fsmonitor for its own repos/taps? Either way, the current error should expose the lock path and holder process so users can diagnose why the message is wrong.
I have seen this error intermittently for years:
Error: Another `brew update` process is already running.
Please wait for it to finish or terminate it to continue.
I always assumed it was some random local breakage in my setup. I only got to the root cause today because an agent helped inspect the lock holder directly.
In this case, there was no active brew update process. The update lock was being held by a detached git fsmonitor--daemon process from a Homebrew tap checkout.
The lock holder was visible with:
lsof /opt/homebrew/var/homebrew/locks/update
Output:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
git 95197 joshka 200w REG ... 0 ... /opt/homebrew/var/homebrew/locks/update
Inspecting that PID showed:
/opt/homebrew/opt/git/libexec/git-core/git fsmonitor--daemon run --detach --ipc-threads=8
It was associated with a Homebrew tap checkout:
/opt/homebrew/Library/Taps/homebrew/homebrew-cask/.git/fsmonitor--daemon.ipc
My global Git config had:
core.fsmonitor true
core.untrackedcache true
Disabling fsmonitor for the Homebrew tap repos and stopping the daemon made brew update work immediately:
git -C /opt/homebrew/Library/Taps/homebrew/homebrew-core config core.fsmonitor false
git -C /opt/homebrew/Library/Taps/homebrew/homebrew-cask config core.fsmonitor false
kill 95197
brew update
After that, brew update ran normally.
The current message gives a false start: it says another brew update process is running, so the natural thing to look for is another brew process. In this case, there was no such process.
The message also does not say:
- which lock could not be acquired
- where that lock file is
- which process currently holds it
- whether the holder is actually a Homebrew process
- what command can be used to inspect the holder
To diagnose the actual cause, a user needs to know:
- Homebrew uses lock files under
$(brew --prefix)/var/homebrew/locks
- the relevant lock is
update
lsof can identify the holder
- Git fsmonitor can run as a detached daemon
- global
core.fsmonitor=true can affect Homebrew tap checkouts
- the daemon may keep the update lock file descriptor open after the original Homebrew process is gone
That is a lot of internal context to need from a short error message. I had seen this for years without it ever bubbling up to a reasonably diagnosable issue.
I do not think git fsmonitor--daemon itself should be treated as inherently suspicious. Git documents core.fsmonitor=true as enabling the built-in filesystem monitor daemon for a working directory, and says it can speed up commands like git status in repositories with many files.
So this may be a reasonable global Git configuration rather than a broken user setup. I barely remembered enabling it; it was likely from general Git performance advice.
That said, I am not sure whether fsmonitor is safe or compatible with the way Homebrew uses Git internally when it is enabled globally by the user.
Current Homebrew code appears to partially account for this already. Library/Homebrew/cmd/update.sh contains this comment:
# Git's fsmonitor prevents the release of our locks
git config --bool core.fsmonitor false
However, that happens after lock update, and it appears to apply only in a narrow repository case rather than to all Homebrew taps. In my case, the lock was held by fsmonitor from homebrew-cask.
At minimum, the error should not assert that another brew update process is running unless the lock holder is actually a Homebrew update process.
When Homebrew cannot acquire the update lock, please include the lock path and, when available, the PID/command currently holding it.
For example:
Error: Homebrew could not acquire the update lock.
Lock: /opt/homebrew/var/homebrew/locks/update
Holder: PID 95197, git fsmonitor--daemon run --detach --ipc-threads=8
If the holder is git fsmonitor--daemon, possible next steps could be one of:
- If it is safe, ignore a lock held only by a detached
git fsmonitor--daemon.
- If fsmonitor is not compatible with Homebrew’s Git usage, override user/global fsmonitor configuration in Homebrew’s own repos/taps, or stop fsmonitor before taking the update lock.
- Keep the current lock behavior, but report the actual holder and suggest disabling fsmonitor for Homebrew repos/taps.
Option 3 seems like the safest minimum change. For example, Homebrew could suggest:
git -C "$(brew --repo homebrew/core)" config core.fsmonitor false
git -C "$(brew --repo homebrew/cask)" config core.fsmonitor false
A brew doctor check for Homebrew lock files held by long-running detached git fsmonitor--daemon processes could also help users who keep seeing this over time.
The important part is that the current message leaves the user looking for another brew update process, which is not what is holding the lock in this case.
This appears related to the older discussion in #13521, but the user-facing failure mode remains difficult to diagnose on current Homebrew.
What is the motivation for the feature?
This would make a long-running and misleading Homebrew lock failure diagnosable from the error itself.
Right now, a user who sees Another brew update process is already running is sent looking for another brew update process. If the real holder is a detached git fsmonitor--daemon, that search does not explain the failure. The user has to know Homebrew’s internal lock path and use lsof to discover the actual holder.
This is especially confusing because core.fsmonitor=true is a reasonable Git performance setting, not an obviously broken Homebrew-specific configuration.
How will the feature be relevant to at least 90% of Homebrew users?
The specific git fsmonitor--daemon case may not affect 90% of users, but clearer lock-holder diagnostics are broadly useful whenever Homebrew cannot acquire a lock. Any user who hits a Homebrew lock error would benefit from seeing which lock is held and which process holds it.
This also reduces support/debugging load because users can distinguish an actual concurrent Homebrew process from a detached helper or other unexpected process.
What alternatives to the feature have been considered?
- Do nothing: users keep seeing a misleading error and need internal Homebrew knowledge to diagnose it.
- Document the workaround only: helpful, but still hard to find when the immediate error does not expose the lock path or holder.
- Tell users to disable Git fsmonitor globally: too broad, because fsmonitor is a reasonable Git performance feature.
- Disable fsmonitor only for Homebrew repos/taps: this may be right if fsmonitor is incompatible with Homebrew’s Git usage, but I am looking for maintainer confirmation on that.
- Ignore locks held only by detached
git fsmonitor--daemon: this may be the best behavior if it can be proven safe, but I do not know enough about Homebrew’s lock semantics to assert that.
Provide a detailed description of the proposed feature
Verification
brew install wget. If they do, open an issue at https://github.com/Homebrew/homebrew-core/issues/new/choose instead.TL;DR: the current update-lock error can be wrong for this case. Homebrew says another
brew updateprocess is running, but the lock holder was actually a detachedgit fsmonitor--daemonprocess from a Homebrew tap checkout. The message also does not expose enough information to understand why it is wrong or how to diagnose the real lock holder.The crisp question is: if the update lock is held only by a detached
git fsmonitor--daemon, is it safe for Homebrew to ignore that lock holder, or should Homebrew instead disable/stop fsmonitor for its own repos/taps? Either way, the current error should expose the lock path and holder process so users can diagnose why the message is wrong.I have seen this error intermittently for years:
I always assumed it was some random local breakage in my setup. I only got to the root cause today because an agent helped inspect the lock holder directly.
In this case, there was no active
brew updateprocess. The update lock was being held by a detachedgit fsmonitor--daemonprocess from a Homebrew tap checkout.The lock holder was visible with:
Output:
Inspecting that PID showed:
It was associated with a Homebrew tap checkout:
My global Git config had:
Disabling fsmonitor for the Homebrew tap repos and stopping the daemon made
brew updatework immediately:After that,
brew updateran normally.The current message gives a false start: it says another
brew updateprocess is running, so the natural thing to look for is anotherbrewprocess. In this case, there was no such process.The message also does not say:
To diagnose the actual cause, a user needs to know:
$(brew --prefix)/var/homebrew/locksupdatelsofcan identify the holdercore.fsmonitor=truecan affect Homebrew tap checkoutsThat is a lot of internal context to need from a short error message. I had seen this for years without it ever bubbling up to a reasonably diagnosable issue.
I do not think
git fsmonitor--daemonitself should be treated as inherently suspicious. Git documentscore.fsmonitor=trueas enabling the built-in filesystem monitor daemon for a working directory, and says it can speed up commands likegit statusin repositories with many files.So this may be a reasonable global Git configuration rather than a broken user setup. I barely remembered enabling it; it was likely from general Git performance advice.
That said, I am not sure whether fsmonitor is safe or compatible with the way Homebrew uses Git internally when it is enabled globally by the user.
Current Homebrew code appears to partially account for this already.
Library/Homebrew/cmd/update.shcontains this comment:However, that happens after
lock update, and it appears to apply only in a narrow repository case rather than to all Homebrew taps. In my case, the lock was held by fsmonitor fromhomebrew-cask.At minimum, the error should not assert that another
brew updateprocess is running unless the lock holder is actually a Homebrew update process.When Homebrew cannot acquire the update lock, please include the lock path and, when available, the PID/command currently holding it.
For example:
If the holder is
git fsmonitor--daemon, possible next steps could be one of:git fsmonitor--daemon.Option 3 seems like the safest minimum change. For example, Homebrew could suggest:
A
brew doctorcheck for Homebrew lock files held by long-running detachedgit fsmonitor--daemonprocesses could also help users who keep seeing this over time.The important part is that the current message leaves the user looking for another
brew updateprocess, which is not what is holding the lock in this case.This appears related to the older discussion in #13521, but the user-facing failure mode remains difficult to diagnose on current Homebrew.
What is the motivation for the feature?
This would make a long-running and misleading Homebrew lock failure diagnosable from the error itself.
Right now, a user who sees
Another brew update process is already runningis sent looking for anotherbrew updateprocess. If the real holder is a detachedgit fsmonitor--daemon, that search does not explain the failure. The user has to know Homebrew’s internal lock path and uselsofto discover the actual holder.This is especially confusing because
core.fsmonitor=trueis a reasonable Git performance setting, not an obviously broken Homebrew-specific configuration.How will the feature be relevant to at least 90% of Homebrew users?
The specific
git fsmonitor--daemoncase may not affect 90% of users, but clearer lock-holder diagnostics are broadly useful whenever Homebrew cannot acquire a lock. Any user who hits a Homebrew lock error would benefit from seeing which lock is held and which process holds it.This also reduces support/debugging load because users can distinguish an actual concurrent Homebrew process from a detached helper or other unexpected process.
What alternatives to the feature have been considered?
git fsmonitor--daemon: this may be the best behavior if it can be proven safe, but I do not know enough about Homebrew’s lock semantics to assert that.