From 41f1ea4672fff9d0c10dab51e8d50127dca19d6c Mon Sep 17 00:00:00 2001 From: Sehoon Shon Date: Wed, 11 Mar 2026 14:22:10 -0400 Subject: [PATCH] fix(core): handle EISDIR in robustRealpath on Windows (#21984) --- packages/core/src/utils/paths.test.ts | 16 ++++++++++++++++ packages/core/src/utils/paths.ts | 9 +++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/packages/core/src/utils/paths.test.ts b/packages/core/src/utils/paths.test.ts index 4563c0485b..590f3aab58 100644 --- a/packages/core/src/utils/paths.test.ts +++ b/packages/core/src/utils/paths.test.ts @@ -528,6 +528,22 @@ describe('resolveToRealPath', () => { expect(resolveToRealPath(input)).toBe(expected); }); + it('should return decoded path even if fs.realpathSync fails with EISDIR', () => { + vi.spyOn(fs, 'realpathSync').mockImplementationOnce(() => { + const err = new Error( + 'Illegal operation on a directory', + ) as NodeJS.ErrnoException; + err.code = 'EISDIR'; + throw err; + }); + + const p = path.resolve('path', 'to', 'New Project'); + const input = pathToFileURL(p).toString(); + const expected = p; + + expect(resolveToRealPath(input)).toBe(expected); + }); + it('should recursively resolve symlinks for non-existent child paths', () => { const parentPath = path.resolve('/some/parent/path'); const resolvedParentPath = path.resolve('/resolved/parent/path'); diff --git a/packages/core/src/utils/paths.ts b/packages/core/src/utils/paths.ts index 338d4017e5..12622fbf86 100644 --- a/packages/core/src/utils/paths.ts +++ b/packages/core/src/utils/paths.ts @@ -384,7 +384,12 @@ function robustRealpath(p: string, visited = new Set()): string { try { return fs.realpathSync(p); } catch (e: unknown) { - if (e && typeof e === 'object' && 'code' in e && e.code === 'ENOENT') { + if ( + e && + typeof e === 'object' && + 'code' in e && + (e.code === 'ENOENT' || e.code === 'EISDIR') + ) { try { const stat = fs.lstatSync(p); if (stat.isSymbolicLink()) { @@ -400,7 +405,7 @@ function robustRealpath(p: string, visited = new Set()): string { lstatError && typeof lstatError === 'object' && 'code' in lstatError && - lstatError.code === 'ENOENT' + (lstatError.code === 'ENOENT' || lstatError.code === 'EISDIR') ) ) { throw lstatError;