{"record":{"id":"d30dc965c4d6c45b","repo":"abhigyanpatwari/GitNexus","slug":"lbug-wipe-failed","errorCode":"lbug-wipe-failed","errorMessage":"Cannot start dirty-state recovery — the interrupted run's LadybugDB sidecars could neither be moved aside nor removed:","messagePattern":"Cannot start dirty-state recovery — the interrupted run's LadybugDB sidecars could neither be moved aside nor removed:","errorType":"exception","errorClass":"LbugWipeError","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/run-analyze.ts","lineNumber":1705,"sourceCode":"            'from the interrupted run (the file could not be moved aside, so its bytes were ' +\n            'removed — post-mortem forensics lost). Recovery proceeds with full embedding ' +\n            'preservation.',\n        );\n      }\n      if (failed.length > 0) {\n        // FIX 1 (this shipping review, replacing the tri-review 4669518496\n        // P2-3 drop-shape design): under a persistent lock the old drop-shape\n        // run derived its embedding mode as \"drop\", ran the WHOLE pipeline,\n        // and then died at the rebuild wipe on the very same handle — wasting\n        // minutes and zeroing embeddings on the way. A possibly-poisoned\n        // sidecar still sits next to the DB (any pre-wipe open would replay it\n        // and die), so failing here, in seconds, with the same actionable\n        // typed error the wipe would eventually throw is strictly better —\n        // and the CLI's LbugWipeError handler already renders it\n        // (recoveryHint 'lbug-wipe-failed'). The message is self-contained\n        // (headline + paths + lock guidance) because serve forwards only\n        // err.message over worker IPC.\n        throw new LbugWipeError(failed, {\n          headline:\n            \"Cannot start dirty-state recovery — the interrupted run's LadybugDB sidecars \" +\n            'could neither be moved aside nor removed:',\n        });\n      }\n    }\n  }\n\n  // ── pdg-mode flip forces full writeback (#2099 F1) ─────────────────\n  // The incremental writeback persists only changed-file nodes, so a pdg\n  // config differing from the one the DB rows were built under cannot be\n  // reconciled incrementally: off→on silently drops the freshly built CFG\n  // layer (\"Incremental: changed=0\", zero BasicBlock rows), on→off strands\n  // zombie blocks for unchanged files. MUST sit before the alreadyUpToDate\n  // fast path below — a clean-tree flip would otherwise early-return without\n  // running the pipeline at all. The notice is deliberately NOT gated on\n  // options.force: --skills implies force with no message of its own, and a\n  // mode change deserves a diagnostic regardless of why a rebuild happens.","sourceCodeStart":1687,"sourceCodeEnd":1723,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/ac9a4e9abd8fd3058c070b72c23402a4f887929a/gitnexus/src/core/run-analyze.ts#L1687-L1723","documentation":"When a previous analyze run died in a dirty state, GitNexus must move or delete the leftover LadybugDB sidecar files before it can start dirty-state recovery. If the quarantine/wipe of those files fails outright, it throws LbugWipeError (code `lbug-wipe-failed`) immediately rather than letting a later database open fail opaquely. The message carries the failed paths and lock guidance, and the CLI renders it with the `lbug-wipe-failed` recovery hint.","triggerScenarios":"`runFullAnalysisInner` detects a dirty previous run and calls the sidecar wipe/quarantine step; the step reports entries in `failed` (files could be neither moved aside nor deleted) — almost always because another process (MCP server or `gitnexus serve`) holds the LadybugDB files open, or OS permissions deny the rename/unlink.","commonSituations":"Leftover `gitnexus serve` or MCP worker from an earlier session still holding the index; analyzing the same repo concurrently from two terminals; read-only or root-owned `.gitnexus` storage after a container/user switch; Windows file locks from an editor or antivirus scanning the WAL.","solutions":["Identify and stop any process holding the repo's LadybugDB files (GitNexus MCP server, `gitnexus serve`, another analyze).","Re-run the command once the lock is released — the wipe is retried at open time and should then succeed.","If no other process exists, fix permissions on the `.gitnexus` storage directory so the files can be renamed/removed.","As a last resort, run `gitnexus clean --lbug-sidecars` manually and then retry `gitnexus analyze`."],"exampleFix":"// before: serve process left running in another terminal\n$ gitnexus analyze\nLbugWipeError: Cannot start dirty-state recovery — ... sidecars could neither be moved aside nor removed\n// after\n$ <kill the lingering `gitnexus serve`/MCP process>\n$ gitnexus analyze   # recovery proceeds, sidecars quarantined","handlingStrategy":"retry","validationCode":"// check for a live lock-holder before starting recovery\nconst { execSync } = require('child_process');\nconst holders = execSync(`lsof +D ${storageDir} 2>/dev/null || true`).toString().trim();\nif (holders) throw new Error('Another process holds the index files; stop it before recovering.');","typeGuard":null,"tryCatchPattern":"try {\n  await runFullAnalysis(opts);\n} catch (e) {\n  if (e.code === 'lbug-wipe-failed') {\n    await stopGitNexusProcesses(repoPath); // stop MCP/serve holders\n    await runFullAnalysis(opts);           // retry once lock is released\n  } else throw e;\n}","preventionTips":["Shut down lingering `gitnexus serve`/MCP processes before recovery runs.","Never analyze the same repository from two concurrent invocations.","Ensure the `.gitnexus` storage directory is writable by the running user.","On Windows/AV setups, exclude the storage directory from real-time file locking."],"tags":["ladybugdb","sidecar","file-lock","recovery","wipe"],"backgroundTag":"file-lock-conflict","analyzedSha":"ac9a4e9abd8fd3058c070b72c23402a4f887929a","analyzedAt":"2026-09-15T23:29:44.066Z","contentChangedAt":"2026-09-15T23:29:44.066Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}