fix(core): handle ENAMETOOLONG in robustRealpath

- Add ENAMETOOLONG to caught errors in robustRealpath to prevent crashes on long paths.
- Add regression test case to verify fix and prevent future regressions.

Fixes https://github.com/google-gemini/gemini-cli/issues/25696
This commit is contained in:
Taylor Mullen 2026-04-20 20:21:54 -07:00
parent 4b2091d402
commit 1902ae5b3f
2 changed files with 21 additions and 3 deletions

View file

@ -601,6 +601,22 @@ describe('resolveToRealPath', () => {
/Infinite recursion detected/,
);
});
it('should return path as-is if fs.realpathSync and fs.lstatSync fail with ENAMETOOLONG', () => {
vi.spyOn(fs, 'realpathSync').mockImplementation(() => {
const err = new Error('File name too long') as NodeJS.ErrnoException;
err.code = 'ENAMETOOLONG';
throw err;
});
vi.spyOn(fs, 'lstatSync').mockImplementation(() => {
const err = new Error('File name too long') as NodeJS.ErrnoException;
err.code = 'ENAMETOOLONG';
throw err;
});
const longPath = path.resolve('a'.repeat(5000));
expect(resolveToRealPath(longPath)).toBe(longPath);
});
});
describe('makeRelative', () => {

View file

@ -424,7 +424,7 @@ function robustRealpath(p: string, visited = new Set<string>()): string {
e &&
typeof e === 'object' &&
'code' in e &&
(e.code === 'ENOENT' || e.code === 'EISDIR')
(e.code === 'ENOENT' || e.code === 'EISDIR' || e.code === 'ENAMETOOLONG')
) {
try {
const stat = fs.lstatSync(p);
@ -435,13 +435,15 @@ function robustRealpath(p: string, visited = new Set<string>()): string {
}
} catch (lstatError: unknown) {
// Not a symlink, or lstat failed. Re-throw if it's not an expected
// ENOENT (e.g., a permissions error), otherwise resolve parent.
// error (e.g., a permissions error), otherwise resolve parent.
if (
!(
lstatError &&
typeof lstatError === 'object' &&
'code' in lstatError &&
(lstatError.code === 'ENOENT' || lstatError.code === 'EISDIR')
(lstatError.code === 'ENOENT' ||
lstatError.code === 'EISDIR' ||
lstatError.code === 'ENAMETOOLONG')
)
) {
throw lstatError;