Skip to content

fix(core): handle ENAMETOOLONG/ENOTDIR in robustRealpath (#26010)#26074

Open
gaurav0107 wants to merge 1 commit intogoogle-gemini:mainfrom
gaurav0107:fix/26010-critical-enametoolong-crash-when-pasting
Open

fix(core): handle ENAMETOOLONG/ENOTDIR in robustRealpath (#26010)#26074
gaurav0107 wants to merge 1 commit intogoogle-gemini:mainfrom
gaurav0107:fix/26010-critical-enametoolong-crash-when-pasting

Conversation

@gaurav0107
Copy link
Copy Markdown
Contributor

Summary

Stops the CLI from crashing with CRITICAL: Unhandled Promise Rejection: ENAMETOOLONG: name too long, lstat '...' when pasting text that the at-mention regex recognizes as a path but that the OS cannot resolve.

Details

packages/core/src/utils/paths.ts::robustRealpath wraps fs.realpathSync(p) and only special-cased ENOENT / EISDIR; every other error code was rethrown unhandled.

The crash path:

  1. User pastes a JSON blob containing a long hex string or an @email.com-style token.
  2. atCommandProcessor.parseAllAtCommands matches it as an atPath (the regex is intentionally generous).
  3. checkPermissions calls resolveToRealPath(path.resolve(targetDir, pathName)).
  4. robustRealpath -> fs.realpathSync(p) -> ENAMETOOLONG -> rethrown -> unhandled promise rejection in the UI layer -> CRITICAL crash banner.

This PR extends the catch branch to treat two additional error codes as non-fatal:

  • ENAMETOOLONG — path component exceeds NAME_MAX / PATH_MAX.
  • ENOTDIR — an intermediate component is a regular file (e.g. @path/to/file.json/extra).

Both semantically mean "this is not a resolvable real path", same as ENOENT. The correct fallback is to return the input unchanged so downstream fileExists / fs.stat callers (which already handle ENOENT gracefully, see atCommandProcessor.ts:301) can reject it normally. Walking up the parent chain (as the existing ENOENT branch does for symlink-aware resolution) would be wrong here because the basename is garbage.

Also factors the repeated typeof e === 'object' && 'code' in e && ... checks into a local hasErrorCode(e, codes) helper. Semantics of the existing ENOENT/EISDIR branch are unchanged.

Related Issues

Closes #26010

How to Validate

Unit tests covering the new branches:

npx vitest run packages/core/src/utils/paths.test.ts

End-to-end: paste a large JSON blob containing strings longer than 255 chars into the prompt — prior to this patch the CLI panics with an unhandled ENAMETOOLONG; after this patch the string is treated as plain text and no path resolution error surfaces.

Full local CI allowlist (all green on this branch):

npm run lint
npm run typecheck
npm run test -w @google/gemini-cli-core    # 7082 passed

(Two pre-existing failures in packages/cli/src/config/extension-manager-*.test.ts reproduce on unmodified upstream main and are unrelated to this change.)

Pre-Merge Checklist

  • Conventional-commit title with scope
  • Closes #N syntax
  • Tests added covering the new branches (ENAMETOOLONG + ENOTDIR)
  • npm run lint clean
  • npm run typecheck clean
  • @google/gemini-cli-core test suite clean
  • No public API changes; resolveToRealPath signature unchanged
  • No behaviour change for valid paths or for the existing ENOENT/EISDIR error branch
  • Cross-platform: both error codes are standard on POSIX and Windows

…ni#26010)

Pasting text that the at-mention regex recognizes as a path — e.g. a
JSON blob containing long hex strings or "@email.com"-style tokens —
caused a CRITICAL unhandled Promise rejection:

    ENAMETOOLONG: name too long, lstat '<very long string>'

`robustRealpath` only special-cased ENOENT / EISDIR in its catch
branch; other error codes were rethrown. ENAMETOOLONG (path component
exceeds OS limit) and ENOTDIR (intermediate component is a regular
file) both mean "this is not a resolvable real path" — the same
semantic as ENOENT — but the correct fallback is to return the input
unchanged rather than walk up the parent chain (whose basename is
garbage in these cases).

Extend the catch handler to treat those two codes as non-fatal and
return the caller's input, matching the behaviour downstream callers
already expect when a probed path doesn't exist on disk.

Also factor the repeated `typeof e === 'object' && 'code' in e && ...`
checks into a local `hasErrorCode(e, codes)` helper for readability;
semantics are unchanged for the existing ENOENT/EISDIR branch.

Adds regression tests for both codes in paths.test.ts alongside the
existing ENOENT/EISDIR coverage.

Closes google-gemini#26010
@gaurav0107 gaurav0107 marked this pull request as ready for review April 27, 2026 20:37
@gaurav0107 gaurav0107 requested a review from a team as a code owner April 27, 2026 20:37
@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 issue where the CLI would crash due to unhandled promise rejections when processing user input that resembles a file path but is invalid or too long for the operating system to resolve. By extending the error handling logic in robustRealpath, the application now treats these specific filesystem errors as non-fatal, allowing the system to continue functioning normally instead of terminating unexpectedly.

Highlights

  • Error Handling Improvement: Updated robustRealpath to gracefully handle ENAMETOOLONG and ENOTDIR errors, preventing CLI crashes when encountering invalid path strings.
  • Code Refactoring: Introduced a helper function hasErrorCode to simplify and standardize error code checking across the codebase.
  • Regression Testing: Added new unit tests in packages/core/src/utils/paths.test.ts to verify that the CLI no longer crashes when these specific filesystem errors occur.
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.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors path resolution logic in packages/core by introducing a hasErrorCode utility for safer error handling. It updates robustRealpath to gracefully handle ENAMETOOLONG and ENOTDIR errors by returning the input path, which prevents crashes when the system encounters long strings or invalid directory structures during path probing. Corresponding regression tests have been added to ensure stability. I have no feedback to provide.

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.

CRITICAL: ENAMETOOLONG crash when pasting large JSON strings

1 participant