{"record":{"id":"f023b92292f24831","repo":"abhigyanpatwari/GitNexus","slug":"gitnexus-could-not-move-the-ladybugdb-wal-sidecar","errorCode":null,"errorMessage":"GitNexus could not move the LadybugDB WAL sidecar at ${dbPath}.wal because of a filesystem permission or file-lock error (${code}). The index does not need to be rebuilt — stop any GitNexus MCP or serve process using this repository, add an antivirus exclusion for the GitNexus storage directory, then re-run the failing command once the lock or permission is resolved.\n  Original error: ${msg.slice(0, 200)}","messagePattern":"GitNexus could not move the LadybugDB WAL sidecar at (.+?)\\.wal because of a filesystem permission or file-lock error \\((.+?)\\)\\. The index does not need to be rebuilt — stop any GitNexus MCP or serve process using this repository, add an antivirus exclusion for the GitNexus storage directory, then re-run the failing command once the lock or permission is resolved\\.\n  Original error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/lbug/lbug-adapter.ts","lineNumber":571,"sourceCode":"): Promise<void> => {\n  // Latitude defaults to refusal. Only the analyze writer passes\n  // `fts-inplace-checkpointed`; serve never does (R9).\n  await guardWalQuarantine(dbPath, mode, triggeringErr, logger, crashEvidence);\n};\n\nconst reopenReadOnlyAfterMissingShadow = async (\n  dbPath: string,\n  err: unknown,\n): Promise<LbugConnectionHandle> => {\n  await refuseLargeWalQuarantine(dbPath, 'read-only', err);\n  try {\n    await quarantineWalForMissingShadow(dbPath, {\n      logger,\n      level: 'warn',\n      reason: 'read-only recovery',\n    });\n  } catch (renameErr) {\n    throw new Error(renameFailureMessage(dbPath, renameErr));\n  }\n\n  const reopened = await openLbugConnection(lbug, dbPath, { readOnly: true });\n  try {\n    await queryAndDrain(reopened.conn, READ_ONLY_SHADOW_REPLAY_PROBE);\n    return reopened;\n  } catch (retryErr) {\n    await closeLbugConnection(reopened);\n    if (isMissingShadowSidecarError(retryErr) || isReadOnlyShadowReplayError(retryErr)) {\n      throw new Error(shadowSidecarRecoveryMessage(dbPath, retryErr));\n    }\n    throw retryErr;\n  }\n};\n\nconst writableFtsCrashWalEvidence = async (\n  dbPath: string,\n): Promise<WalCrashEvidence | undefined> => {","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/ac9a4e9abd8fd3058c070b72c23402a4f887929a/gitnexus/src/core/lbug/lbug-adapter.ts#L553-L589","documentation":"renameFailureMessage from lbug-adapter.ts (read-only recovery path, line 575): while recovering from a missing checkpoint sidecar, GitNexus tries to quarantine the WAL sidecar (${dbPath}.wal) by renaming it; the rename fails with a filesystem permission or file-lock errno (code). The message is explicit that the index does NOT need rebuilding — an external holder (another process, antivirus) is blocking the rename.","triggerScenarios":"Antivirus/real-time scanning holding the .wal file open (typical on Windows); a concurrently running `gitnexus serve` or MCP process with an open handle on the database; storage directory on a read-only mount or with restrictive permissions; network filesystems that refuse locked renames.","commonSituations":"Windows workstations with Defender real-time protection scanning ~/.gitnexus; an MCP server left running in the IDE while maintenance commands execute; indexes stored on SMB/NFS shares.","solutions":["Stop any GitNexus MCP or serve process using this repository, then re-run the failing command","Add an antivirus exclusion for the GitNexus storage directory (e.g. ~/.gitnexus)","Verify write permission on the storage directory and that it is not on a read-only filesystem","Re-run the command once the lock/permission is resolved — no rebuild is needed"],"exampleFix":"# before\n# (serve running, AV scanning ~/.gitnexus)\n$ gitnexus serve & gitnexus query ...\n# after\n$ gitnexus mcp stop\n# Add AV exclusion for ~/.gitnexus, then:\ngitnexus query ...","handlingStrategy":"retry","validationCode":"import fs from 'node:fs';\n\nfs.accessSync(path.dirname(dbPath), fs.constants.W_OK); // throws early if storage is not writable\nfs.accessSync(`${dbPath}.wal`, fs.constants.W_OK);       // surfaces permission problems before recovery renames","typeGuard":null,"tryCatchPattern":"try {\n  await openAndQuery(dbPath);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('could not move the LadybugDB WAL sidecar')) {\n    // stop serve/MCP processes, add an AV exclusion, then re-run once — the index itself is intact, no rebuild\n  }\n  throw err;\n}","preventionTips":["Add the GitNexus storage directory (e.g. ~/.gitnexus) to antivirus real-time-scan exclusions on Windows","Stop serve/MCP processes before running maintenance or recovery-triggering commands against the same index","Keep the storage directory on a local writable filesystem, not a locked network share"],"tags":["wal","ladybugdb","filesystem","permissions","antivirus","windows","recovery"],"backgroundTag":"file-lock-violation","analyzedSha":"ac9a4e9abd8fd3058c070b72c23402a4f887929a","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}