Skip to content

fix(core): prevent ENOENT crash due to proper-lockfile race condition#25885

Closed
spencer426 wants to merge 5 commits into
mainfrom
unable-to-start
Closed

fix(core): prevent ENOENT crash due to proper-lockfile race condition#25885
spencer426 wants to merge 5 commits into
mainfrom
unable-to-start

Conversation

@spencer426

Copy link
Copy Markdown
Contributor

Summary

This PR fixes a critical startup crash where the CLI exits with an unhandled
exception:
Error: ENOENT: no such file or directory, stat '.../.gemini/projects.json.lock'.

This addresses the bug where the CLI occasionally hangs or crashes on launch,
particularly when multiple commands are run in quick succession or under heavy
concurrent load.

Details

The crash is caused by an internal race condition within the proper-lockfile
package.

When we acquire a lock (e.g., for projects.json or trusted_folders.json),
proper-lockfile sets up a background interval (setTimeout) to periodically
update the lock directory's mtime so that the lock doesn't become "stale".
This update process calls fs.stat on the .lock directory.

The race condition occurs if the CLI finishes its task and releases the lock
(which deletes the .lock directory) at the exact moment the background stat
operation is pending in the event loop. When the stat callback eventually
fires, the directory is already gone, yielding an ENOENT error.

By default, proper-lockfile treats an ENOENT during an update as a
"compromised lock" and triggers its onCompromised handler. The default
implementation of this handler is (err) => { throw err; }, which results in an
unhandled asynchronous exception that crashes the entire Node process.

This PR implements explicit onCompromised handlers anywhere we call lock()
(specifically in ProjectRegistry and trust.ts). By providing a custom
callback that catches and logs (or safely ignores) the ECOMPROMISED event, we
prevent proper-lockfile from throwing the unhandled exception.

Related Issues

Fixes #1631

How to Validate

  1. Run npm run test -w packages/core to ensure no regressions in configuration
    or trust management.
  2. The isolated reproduction script in the issue confirms that intercepting the
    stat call and calling release() manually perfectly reproduces the crash
    without the fix, and successfully catches the error with the fix.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

@spencer426 spencer426 requested a review from a team as a code owner April 23, 2026 20:47
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical startup crash caused by a race condition in the proper-lockfile package. By providing explicit handlers for compromised locks, the application now safely manages scenarios where a lock directory is removed while a background status check is still pending, preventing unhandled exceptions and improving overall CLI stability under load.

Highlights

  • Race condition resolution: Implemented custom onCompromised handlers for proper-lockfile to prevent unhandled ENOENT exceptions during concurrent lock operations.
  • Improved stability: Added error handling in ProjectRegistry and LoadedTrustedFolders to gracefully manage lock compromise events instead of crashing the process.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

gemini-code-assist[bot]

This comment was marked as outdated.

@github-actions

github-actions Bot commented Apr 23, 2026

Copy link
Copy Markdown

Size Change: +349 B (0%)

Total Size: 33.9 MB

Filename Size Change
./bundle/chunk-2RZW36XG.js 0 B -2.72 MB (removed) 🏆
./bundle/chunk-5ETPHYRS.js 0 B -3.43 kB (removed) 🏆
./bundle/chunk-DZWYS2UO.js 0 B -656 kB (removed) 🏆
./bundle/chunk-JBQENBXL.js 0 B -49.2 kB (removed) 🏆
./bundle/chunk-LCJFAVLT.js 0 B -3.8 kB (removed) 🏆
./bundle/chunk-LHXIF4FS.js 0 B -12.6 kB (removed) 🏆
./bundle/chunk-MQY5AD2C.js 0 B -14.7 MB (removed) 🏆
./bundle/chunk-OQX7GVID.js 0 B -1.97 MB (removed) 🏆
./bundle/chunk-TLJ7C6I2.js 0 B -19.5 kB (removed) 🏆
./bundle/core-DUTCIE7U.js 0 B -48.2 kB (removed) 🏆
./bundle/devtoolsService-SUNVBJG5.js 0 B -28 kB (removed) 🏆
./bundle/gemini-K3CBINQJ.js 0 B -580 kB (removed) 🏆
./bundle/interactiveCli-3GSGECQL.js 0 B -1.32 MB (removed) 🏆
./bundle/liteRtServerManager-OWPQIOM3.js 0 B -2.11 kB (removed) 🏆
./bundle/oauth2-provider-DY7W77PO.js 0 B -9.16 kB (removed) 🏆
./bundle/chunk-46NNZQPR.js 1.97 MB +1.97 MB (new file) 🆕
./bundle/chunk-563RHJLR.js 14.7 MB +14.7 MB (new file) 🆕
./bundle/chunk-5BVMI2BL.js 3.43 kB +3.43 kB (new file) 🆕
./bundle/chunk-JCQGPORZ.js 19.5 kB +19.5 kB (new file) 🆕
./bundle/chunk-LLCFQF7R.js 656 kB +656 kB (new file) 🆕
./bundle/chunk-MANKY4IN.js 2.72 MB +2.72 MB (new file) 🆕
./bundle/chunk-MMMOI3GZ.js 12.6 kB +12.6 kB (new file) 🆕
./bundle/chunk-O3JEXX2C.js 49.2 kB +49.2 kB (new file) 🆕
./bundle/chunk-ZW2OJP4U.js 3.8 kB +3.8 kB (new file) 🆕
./bundle/core-ZWY4O3OX.js 48.2 kB +48.2 kB (new file) 🆕
./bundle/devtoolsService-TBUJGUH7.js 28 kB +28 kB (new file) 🆕
./bundle/gemini-2JDTPN4Q.js 580 kB +580 kB (new file) 🆕
./bundle/interactiveCli-RMHWWTUR.js 1.32 MB +1.32 MB (new file) 🆕
./bundle/liteRtServerManager-3322RNHE.js 2.11 kB +2.11 kB (new file) 🆕
./bundle/oauth2-provider-BNPNF36W.js 9.16 kB +9.16 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size Change
./bundle/bundled/third_party/index.js 8 MB 0 B
./bundle/chunk-34MYV7JD.js 2.45 kB 0 B
./bundle/chunk-5AUYMPVF.js 858 B 0 B
./bundle/chunk-5PS3AYFU.js 1.18 kB 0 B
./bundle/chunk-664ZODQF.js 124 kB 0 B
./bundle/chunk-DAHVX5MI.js 206 kB 0 B
./bundle/chunk-IUUIT4SU.js 56.5 kB 0 B
./bundle/chunk-RJTRUG2J.js 39.8 kB 0 B
./bundle/cleanup-W7KM7K6R.js 0 B -932 B (removed) 🏆
./bundle/devtools-36NN55EP.js 696 kB 0 B
./bundle/dist-T73EYRDX.js 356 B 0 B
./bundle/events-XB7DADIJ.js 418 B 0 B
./bundle/examples/hooks/scripts/on-start.js 188 B 0 B
./bundle/examples/mcp-server/example.js 1.43 kB 0 B
./bundle/gemini.js 5.14 kB 0 B
./bundle/getMachineId-bsd-TXG52NKR.js 1.55 kB 0 B
./bundle/getMachineId-darwin-7OE4DDZ6.js 1.55 kB 0 B
./bundle/getMachineId-linux-SHIFKOOX.js 1.34 kB 0 B
./bundle/getMachineId-unsupported-5U5DOEYY.js 1.06 kB 0 B
./bundle/getMachineId-win-6KLLGOI4.js 1.72 kB 0 B
./bundle/memoryDiscovery-QEUOLE5X.js 0 B -980 B (removed) 🏆
./bundle/multipart-parser-KPBZEGQU.js 11.7 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 222 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 229 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 13.4 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B 0 B
./bundle/sandbox-macos-permissive-open.sb 890 B 0 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB 0 B
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB 0 B
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB 0 B
./bundle/sandbox-macos-strict-open.sb 4.82 kB 0 B
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB 0 B
./bundle/src-QVCVGIUX.js 47 kB 0 B
./bundle/start-UDEBH3P5.js 0 B -652 B (removed) 🏆
./bundle/tree-sitter-7U6MW5PS.js 274 kB 0 B
./bundle/tree-sitter-bash-34ZGLXVX.js 1.84 MB 0 B
./bundle/cleanup-YBIVYBOZ.js 932 B +932 B (new file) 🆕
./bundle/memoryDiscovery-W7CUKRXZ.js 980 B +980 B (new file) 🆕
./bundle/start-HAVOEYB6.js 652 B +652 B (new file) 🆕

compressed-size-action

@gemini-cli gemini-cli Bot added the priority/p0 Critical and urgent (e.g., critical security vulnerability, major breakage). label Apr 23, 2026
@spencer426 spencer426 force-pushed the unable-to-start branch 2 times, most recently from a24be6c to cf3a01e Compare April 23, 2026 21:13
@spencer426 spencer426 requested a review from a team as a code owner April 23, 2026 21:13
@spencer426 spencer426 force-pushed the unable-to-start branch 2 times, most recently from 4adfcca to d80fccd Compare April 23, 2026 22:07
@google-gemini google-gemini deleted a comment from gemini-code-assist Bot Apr 23, 2026
@gemini-cli

gemini-cli Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

Hi there! Thank you for your interest in contributing to Gemini CLI.

To ensure we maintain high code quality and focus on our prioritized roadmap, we only guarantee review and consideration of pull requests for issues that are explicitly labeled as 'help wanted'.

This PR will be closed in 7 days if it remains without that designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding.

@gemini-cli

gemini-cli Bot commented May 8, 2026

Copy link
Copy Markdown
Contributor

This pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding.

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

Labels

priority/p0 Critical and urgent (e.g., critical security vulnerability, major breakage). size/m A medium sized PR status/pr-nudge-sent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Looping on ℹ ⚡ Rate limiting detected. Automatically switching ....

2 participants