abhigyanpatwari/GitNexus · warning

GitNexus: manual WAL checkpoint failed after retries

Error message

GitNexus: manual WAL checkpoint failed after retries

What it means

The periodic manual WAL checkpoint driver (runCheckpointWithRetry under withConnLock, with a bounded retry budget) exhausted its retries. The comment spells out the contract: the surrounding write will see the same engine error on its next operation, and analyzeCommand's catch block emits the user-facing recovery hint — this warn is the operator-visible trail without double-logging. Skips while a checkpoint is inflight so attempts do not pile up.

Source

Thrown at gitnexus/src/core/lbug/wal-checkpoint-driver.ts:191

  const tick = async (): Promise<void> => {
    if (stopped) return;
    // Reentrancy guard: setInterval keeps firing on its fixed cadence even when
    // the previous checkpoint has not settled (a CHECKPOINT can outlast the
    // period during a large `--pdg` writeback). Without this, each overdue tick
    // would queue another CHECKPOINT — they now serialize on the connection lock
    // (lbug-adapter `withConnLock`), but letting them pile up is still pointless
    // work and widens the window for a backlog at stop(). Skip while one is in
    // flight; the next tick covers any WAL accumulated in the meantime.
    if (inflight) return;
    inflight = runCheckpointWithRetry()
      .then(() => undefined)
      .catch((err) => {
        // The retry budget exhausted. The caller's surrounding write
        // will see the same engine error on its next operation and the
        // `analyzeCommand` catch block will emit the recovery hint.
        // Logging here keeps the operator-visible trail without
        // double-logging the user-facing message.
        logger.warn(
          { err: err instanceof Error ? err.message : String(err) },
          'GitNexus: manual WAL checkpoint failed after retries',
        );
      });
    try {
      await inflight;
    } finally {
      inflight = null;
    }
  };

  const handle = setInterval(() => {
    // Fire-and-forget: setInterval cannot await directly. The next tick
    // is guarded by `stopped` and the `inflight` reference.
    void tick();
  }, periodMs);
  // `setInterval` returned by Node is a `Timeout` object with `.unref()`
  // so a hung driver never prevents process exit.

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Stop the concurrent reader (serve/MCP queries) during indexing so the checkpoint can complete, then re-run.
  2. Watch for the analyzeCommand recovery hint that follows — it names the suggested action for the underlying engine error.
  3. Add antivirus exclusions for the .gitnexus directory (WAL + shadow files).
  4. If WAL corruption is the cause, rebuild the DB from scratch rather than retrying into a corrupt WAL.
Defensive patterns

Strategy: retry

Validate before calling

// Reduce contention before the write that triggers checkpoints:
// pause MCP/serve traffic, or run analyze in an exclusive window
if (serveTrafficActive()) await pauseServeOrScheduleAnalyze();

Try / catch

try {
  await runCheckpointWithRetry(); // the driver's own budget
} catch (err) {
  // matches the driver: let the surrounding write surface the engine error +
  // analyzeCommand's recovery hint; retry after clearing long-running readers
  await clearReaders();
  await runCheckpointWithRetry();
}

Prevention

When it happens

Trigger: The interval-driven checkpoint fires after writes; CHECKPOINT keeps failing across the whole retry budget — long-running readers pinning the WAL, EBUSY from concurrent access, antivirus interference, or WAL corruption. The next tick would retry, but the failure means WAL growth continues until then.

Common situations: `gitnexus serve` answering long queries while analyze writes (readers block checkpoint); Windows Defender scanning WAL files; DBs on network volumes; large indexes with heavy churn between ticks.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20). Data as JSON: /api/errors/d265636af095d332. Report an issue: GitHub.