diff --git a/gitnexus/src/core/lbug/sidecar-recovery.ts b/gitnexus/src/core/lbug/sidecar-recovery.ts index f9e86719d..b34b4d905 100644 --- a/gitnexus/src/core/lbug/sidecar-recovery.ts +++ b/gitnexus/src/core/lbug/sidecar-recovery.ts @@ -113,7 +113,9 @@ const warnOnce = (logger: SidecarRecoveryLogger, key: string, message: string): // — `git grep "LADYBUGDB-CONTRACT"` enumerates every version-coupled spot. export const isMissingShadowSidecarError = (err: unknown): boolean => { const msg = err instanceof Error ? err.message : String(err); - return /Cannot open file .*\.shadow: No such file or directory/i.test(msg); + return /Cannot open file(?:\. path:)? .*\.shadow(?:: No such file or directory| - Error 2: The system cannot find the file specified\.?)/i.test( + msg, + ); }; // LADYBUGDB-CONTRACT: matches @ladybugdb/core ^0.16.1 native error text. diff --git a/gitnexus/test/unit/sidecar-recovery.test.ts b/gitnexus/test/unit/sidecar-recovery.test.ts index c0a2c4752..ce550c90f 100644 --- a/gitnexus/test/unit/sidecar-recovery.test.ts +++ b/gitnexus/test/unit/sidecar-recovery.test.ts @@ -7,6 +7,7 @@ import { _resetSidecarRecoveryWarningsForTest, finalizeLbugSidecarsAfterClose, inspectLbugSidecars, + isMissingShadowSidecarError, isPermissionRenameError, isReadOnlyShadowReplayError, listQuarantinedMissingShadowWals, @@ -184,6 +185,24 @@ describe('LadybugDB sidecar recovery', () => { }); describe('Centralized isReadOnlyShadowReplayError (PR #1747 review, F4 dedup)', () => { + it('matches LadybugDB missing-shadow errors on both Unix and Windows formats', () => { + const unixErr = new Error( + 'IO exception: Cannot open file /tmp/lbug.shadow: No such file or directory', + ); + const winErr = new Error( + 'IO exception: Cannot open file. path: D:\\repo\\.gitnexus\\lbug.shadow - Error 2: The system cannot find the file specified.', + ); + expect(isMissingShadowSidecarError(unixErr)).toBe(true); + expect(isMissingShadowSidecarError(winErr)).toBe(true); + }); + + it('false-positive guard: missing-shadow matcher rejects unrelated errors', () => { + expect(isMissingShadowSidecarError(new Error('file not found'))).toBe(false); + expect( + isMissingShadowSidecarError(new Error('Cannot open file /tmp/lbug.wal: lock conflict')), + ).toBe(false); + }); + it('matches LadybugDB read-only shadow-replay error', () => { const err = new Error( "Runtime exception: Couldn't replay shadow pages under read-only mode. Please re-open the database with read-write mode to replay shadow pages.",