@@ -46,6 +46,15 @@ import { Config, type GeminiCLIExtension } from '../config/config.js';
4646import { Storage } from '../config/storage.js' ;
4747import { SimpleExtensionLoader } from './extensionLoader.js' ;
4848import { CoreEvent , coreEvents } from './events.js' ;
49+ import * as fs from 'node:fs' ;
50+
51+ vi . mock ( 'node:fs' , async ( importOriginal ) => {
52+ const actual = await importOriginal < typeof import ( 'node:fs' ) > ( ) ;
53+ return {
54+ ...actual ,
55+ realpathSync : vi . fn ( actual . realpathSync ) ,
56+ } ;
57+ } ) ;
4958
5059vi . mock ( 'os' , async ( importOriginal ) => {
5160 const actualOs = await importOriginal < typeof os > ( ) ;
@@ -743,6 +752,40 @@ included directory memory
743752 expect ( result . filePaths ) . toContain ( projectContextFile ) ;
744753 } ) ;
745754
755+ it ( 'should not crash when fs.realpathSync throws EISDIR on virtual drive roots' , async ( ) => {
756+ // Mock realpathSync to throw EISDIR for a specific path, simulating
757+ // the Windows virtual drive issue (#25216).
758+ vi . mocked ( fs . realpathSync ) . mockImplementation ( ( p : fs . PathLike ) => {
759+ const pathStr = p . toString ( ) ;
760+ if ( pathStr . includes ( 'virtual-drive' ) ) {
761+ const error = new Error (
762+ "EISDIR: illegal operation on a directory, realpath 'A:\\a'" ,
763+ ) ;
764+
765+ ( error as NodeJS . ErrnoException ) . code = 'EISDIR' ;
766+ throw error ;
767+ }
768+ // For other paths, we need to return something sensible.
769+ // Since it's a mock, we can just return the path string itself.
770+ return pathStr ;
771+ } ) ;
772+
773+ const virtualDriveCwd = path . join ( testRootDir , 'virtual-drive' ) ;
774+ await fsPromises . mkdir ( virtualDriveCwd , { recursive : true } ) ;
775+
776+ // This should now succeed instead of throwing
777+ const result = await loadServerHierarchicalMemory (
778+ virtualDriveCwd ,
779+ [ ] ,
780+ new FileDiscoveryService ( projectRoot ) ,
781+ new SimpleExtensionLoader ( [ ] ) ,
782+ DEFAULT_FOLDER_TRUST ,
783+ ) ;
784+
785+ expect ( result ) . toBeDefined ( ) ;
786+ expect ( result . fileCount ) . toBe ( 0 ) ;
787+ } ) ;
788+
746789 it ( 'silently skips a GEMINI.md symlink that points to a directory' , async ( ) => {
747790 // Create a real directory elsewhere and symlink GEMINI.md to it.
748791 const realDir = await createEmptyDir ( path . join ( cwd , '.geminimd-target' ) ) ;
0 commit comments