{"record":{"id":"fdaaa7e26933d59e","repo":"abhigyanpatwari/GitNexus","slug":"ladybugdb-checkpoint-sidecar-is-present-but-unreac","errorCode":null,"errorMessage":"LadybugDB checkpoint sidecar is present but unreachable for ${dbPath}. The .shadow file is on disk, so the open likely failed on path reachability or a file lock (antivirus, another process holding a handle, or a non-ASCII path) rather than a missing sidecar. Check filesystem access and locks; only run `gitnexus analyze --force <repo-path> --index-only` if the index is genuinely broken.\n  Original error: ${msg.slice(0, 200)}","messagePattern":"LadybugDB checkpoint sidecar is present but unreachable for (.+?)\\. The \\.shadow file is on disk, so the open likely failed on path reachability or a file lock \\(antivirus, another process holding a handle, or a non-ASCII path\\) rather than a missing sidecar\\. Check filesystem access and locks; only run `gitnexus analyze --force <repo-path> --index-only` if the index is genuinely broken\\.\n  Original error: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/lbug/sidecar-recovery.ts","lineNumber":310,"sourceCode":" * the existing recovery path is safe to proceed. `mode` is a label used only in\n * the warning text (e.g. 'read-only', 'writable', 'pool read-only recovery').\n */\nexport const guardWalQuarantine = async (\n  dbPath: string,\n  mode: string,\n  triggeringErr: unknown,\n  logger: SidecarRecoveryLogger,\n): Promise<void> => {\n  const state = await inspectLbugSidecars(dbPath);\n  if (state.kind === 'wal-with-shadow') {\n    warnOnce(\n      logger,\n      `${dbPath}:present-shadow-refuse:${mode}`,\n      `GitNexus: refusing to quarantine WAL at ${dbPath}.wal during ${mode} recovery — ` +\n        'the .shadow sidecar is present on disk, so the open likely failed on path reachability or a lock ' +\n        'rather than a missing shadow. Run `gitnexus analyze --force <repo-path> --index-only` if the index is genuinely broken.',\n    );\n    throw new Error(presentShadowUnreachableMessage(dbPath, triggeringErr));\n  }\n  if (state.kind === 'orphan-wal') {\n    warnOnce(\n      logger,\n      `${dbPath}:large-wal-refuse:${mode}`,\n      `GitNexus: refusing to quarantine large WAL (${state.walBytes} bytes) at ${dbPath}.wal during ${mode} recovery; ` +\n        'manual recovery required — run `gitnexus analyze --force <repo-path> --index-only`.',\n    );\n    throw new Error(shadowSidecarRecoveryMessage(dbPath, triggeringErr));\n  }\n};\n\nexport async function quarantineWalForMissingShadow(\n  dbPath: string,\n  options: {\n    logger: SidecarRecoveryLogger;\n    level?: 'debug' | 'info' | 'warn';\n    reason?: string;","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/core/lbug/sidecar-recovery.ts#L292-L328","documentation":"Thrown by enforceSidecarRecoveryPolicy when the sidecar inspection finds the .shadow file IS present on disk (state.kind === 'wal-with-shadow') but the DB open still failed. This is distinct from a genuinely missing sidecar: the shadow checkpoint data exists, so the failure was caused by path reachability (non-ASCII path, permission), a file lock (antivirus, another process), or an I/O error — not by missing checkpoint data. The error deliberately does NOT advise rebuilding the index (that would be destructive and unnecessary); instead it tells the user to check filesystem access and locks. The original triggering error is truncated to 200 chars and appended.","triggerScenarios":"During DB open recovery, inspectLbugSidecars detects the .shadow file exists alongside the .wal, but the open failed. This happens when the filesystem can see the file (stat succeeds) but can't read/mmap it — e.g. restrictive file permissions, a file lock held by antivirus or another GitNexus process, a non-ASCII path that confuses the native library, or an NFS/network filesystem I/O timeout.","commonSituations":"Windows Defender locking the .shadow file during open; another GitNexus serve/MCP process holding the file; restrictive permissions on the .gitnexus/ directory; a non-ASCII character in the repo path (common with non-English usernames on Windows); NFS mount with stale file handles.","solutions":["Stop all GitNexus processes and retry — the file lock from another process is the most common cause","Add an antivirus exclusion for the GitNexus storage directory","Check file permissions on the .shadow file and its parent directory — the GitNexus process needs read access","If the repo path contains non-ASCII characters, move the repo or configure a storage root with an ASCII-only path","Only run `gitnexus analyze --force <repo-path> --index-only` if you've confirmed the index is genuinely broken (not just locked)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Verify .shadow file is accessible before attempting recovery\nimport { access, constants } from 'fs/promises';\nasync function isShadowAccessible(dbPath: string): Promise<boolean> {\n  try {\n    await access(`${dbPath}.shadow`, constants.R_OK);\n    return true;\n  } catch {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await enforceSidecarRecoveryPolicy(dbPath, mode, triggeringErr, logger);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('present but unreachable')) {\n    // Don't rebuild — fix the lock/path issue instead\n    logger.error('Shadow sidecar present but locked — stop concurrent processes, check permissions');\n  }\n  throw e;\n}","preventionTips":["Stop all GitNexus processes before attempting DB recovery to clear file locks","Add antivirus exclusions for the .gitnexus/ storage directory on Windows","Avoid non-ASCII characters in repository paths — use ASCII-only paths for GitNexus storage","Check file permissions regularly: the GitNexus user needs read/write access to all .gitnexus/ files"],"tags":["ladybugdb","sidecar","shadow","file-lock","checkpoint","recovery"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}