abhigyanpatwari/GitNexus · error · LbugWipeError

lbug-wipe-failed

lbug-wipe-failed

Error message

Cannot start dirty-state recovery — the interrupted run's LadybugDB sidecars could neither be moved aside nor removed:

What it means

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.

Solutions

  1. Identify and stop any process holding the repo's LadybugDB files (GitNexus MCP server, `gitnexus serve`, another analyze).
  2. Re-run the command once the lock is released — the wipe is retried at open time and should then succeed.
  3. If no other process exists, fix permissions on the `.gitnexus` storage directory so the files can be renamed/removed.
  4. As a last resort, run `gitnexus clean --lbug-sidecars` manually and then retry `gitnexus analyze`.

Example fix

// before: serve process left running in another terminal
$ gitnexus analyze
LbugWipeError: Cannot start dirty-state recovery — ... sidecars could neither be moved aside nor removed
// after
$ <kill the lingering `gitnexus serve`/MCP process>
$ gitnexus analyze   # recovery proceeds, sidecars quarantined
Defensive patterns

Strategy: retry

Validate before calling

// check for a live lock-holder before starting recovery
const { execSync } = require('child_process');
const holders = execSync(`lsof +D ${storageDir} 2>/dev/null || true`).toString().trim();
if (holders) throw new Error('Another process holds the index files; stop it before recovering.');

Try / catch

try {
  await runFullAnalysis(opts);
} catch (e) {
  if (e.code === 'lbug-wipe-failed') {
    await stopGitNexusProcesses(repoPath); // stop MCP/serve holders
    await runFullAnalysis(opts);           // retry once lock is released
  } else throw e;
}

Prevention

When it happens

Trigger: `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.

Common situations: 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.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15). Data as JSON: /api/errors/d30dc965c4d6c45b. Report an issue: GitHub.

Appendix: source

Thrown at gitnexus/src/core/run-analyze.ts:1705

            'from the interrupted run (the file could not be moved aside, so its bytes were ' +
            'removed — post-mortem forensics lost). Recovery proceeds with full embedding ' +
            'preservation.',
        );
      }
      if (failed.length > 0) {
        // FIX 1 (this shipping review, replacing the tri-review 4669518496
        // P2-3 drop-shape design): under a persistent lock the old drop-shape
        // run derived its embedding mode as "drop", ran the WHOLE pipeline,
        // and then died at the rebuild wipe on the very same handle — wasting
        // minutes and zeroing embeddings on the way. A possibly-poisoned
        // sidecar still sits next to the DB (any pre-wipe open would replay it
        // and die), so failing here, in seconds, with the same actionable
        // typed error the wipe would eventually throw is strictly better —
        // and the CLI's LbugWipeError handler already renders it
        // (recoveryHint 'lbug-wipe-failed'). The message is self-contained
        // (headline + paths + lock guidance) because serve forwards only
        // err.message over worker IPC.
        throw new LbugWipeError(failed, {
          headline:
            "Cannot start dirty-state recovery — the interrupted run's LadybugDB sidecars " +
            'could neither be moved aside nor removed:',
        });
      }
    }
  }

  // ── pdg-mode flip forces full writeback (#2099 F1) ─────────────────
  // The incremental writeback persists only changed-file nodes, so a pdg
  // config differing from the one the DB rows were built under cannot be
  // reconciled incrementally: off→on silently drops the freshly built CFG
  // layer ("Incremental: changed=0", zero BasicBlock rows), on→off strands
  // zombie blocks for unchanged files. MUST sit before the alreadyUpToDate
  // fast path below — a clean-tree flip would otherwise early-return without
  // running the pipeline at all. The notice is deliberately NOT gated on
  // options.force: --skills implies force with no message of its own, and a
  // mode change deserves a diagnostic regardless of why a rebuild happens.

View on GitHub (pinned to ac9a4e9abd)