@@ -1921,6 +1921,66 @@ describe("storage", () => {
19211921 }
19221922 } ) ;
19231923
1924+ it ( "skips seed write when project path access fails with non-ENOENT error" , async ( ) => {
1925+ const fakeHome = join ( testWorkDir , "home-fallback-access-error" ) ;
1926+ const projectDir = join ( testWorkDir , "project-fallback-access-error" ) ;
1927+ const projectGitDir = join ( projectDir , ".git" ) ;
1928+ const globalConfigDir = join ( fakeHome , ".opencode" ) ;
1929+ const globalStoragePath = join ( globalConfigDir , "openai-codex-accounts.json" ) ;
1930+
1931+ await fs . mkdir ( fakeHome , { recursive : true } ) ;
1932+ await fs . mkdir ( projectGitDir , { recursive : true } ) ;
1933+ await fs . mkdir ( globalConfigDir , { recursive : true } ) ;
1934+ process . env . HOME = fakeHome ;
1935+ process . env . USERPROFILE = fakeHome ;
1936+ setStoragePath ( projectDir ) ;
1937+
1938+ const globalStorage = {
1939+ version : 3 ,
1940+ activeIndex : 0 ,
1941+ accounts : [
1942+ {
1943+ refreshToken : "global-refresh-access-error" ,
1944+ accountId : "global-account-access-error" ,
1945+ addedAt : 1 ,
1946+ lastUsed : 1 ,
1947+ } ,
1948+ ] ,
1949+ } ;
1950+ await fs . writeFile ( globalStoragePath , JSON . stringify ( globalStorage ) , "utf-8" ) ;
1951+
1952+ const projectScopedPath = getStoragePath ( ) ;
1953+ const originalAccess = fs . access . bind ( fs ) ;
1954+ const originalRename = fs . rename . bind ( fs ) ;
1955+ let projectSeedWriteCount = 0 ;
1956+
1957+ const accessSpy = vi . spyOn ( fs , "access" ) . mockImplementation ( async ( path , mode ) => {
1958+ if ( String ( path ) === projectScopedPath ) {
1959+ const err = new Error ( "EACCES access failure" ) as NodeJS . ErrnoException ;
1960+ err . code = "EACCES" ;
1961+ throw err ;
1962+ }
1963+ return originalAccess ( path as string , mode ) ;
1964+ } ) ;
1965+
1966+ const renameSpy = vi . spyOn ( fs , "rename" ) . mockImplementation ( async ( sourcePath , destinationPath ) => {
1967+ if ( String ( destinationPath ) === projectScopedPath ) {
1968+ projectSeedWriteCount += 1 ;
1969+ }
1970+ return originalRename ( sourcePath , destinationPath ) ;
1971+ } ) ;
1972+
1973+ try {
1974+ const loaded = await loadAccounts ( ) ;
1975+ expect ( loaded ?. accounts [ 0 ] ?. accountId ) . toBe ( "global-account-access-error" ) ;
1976+ expect ( projectSeedWriteCount ) . toBe ( 0 ) ;
1977+ expect ( existsSync ( projectScopedPath ) ) . toBe ( false ) ;
1978+ } finally {
1979+ accessSpy . mockRestore ( ) ;
1980+ renameSpy . mockRestore ( ) ;
1981+ }
1982+ } ) ;
1983+
19241984 it ( "returns null when global fallback storage is corrupted" , async ( ) => {
19251985 const fakeHome = join ( testWorkDir , "home-fallback-corrupted" ) ;
19261986 const projectDir = join ( testWorkDir , "project-fallback-corrupted" ) ;
0 commit comments