abhigyanpatwari/GitNexus · error · Error

GitNexus could not move the LadybugDB WAL sidecar at ${dbPat

Error message

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}

What it means

Thrown on the read-only recovery path (`reopenReadOnlyAfterMissingShadow`) when quarantining the WAL sidecar (renaming `.wal` aside to recover) fails with a filesystem permission or file-lock error. `renameFailureMessage` classifies the cause: EACCES/EPERM/EBUSY produce a permission/lock-specific message (no rebuild needed — the index is fine once the lock clears), while other codes fall through to the rebuild message. This is the read-only branch that runs when a serve/MCP path hits a missing checkpoint `.shadow`.

Source

Thrown at gitnexus/src/core/lbug/lbug-adapter.ts:575

  mode: 'read-only' | 'writable',
  triggeringErr: unknown,
): Promise<void> => {
  await guardWalQuarantine(dbPath, mode, triggeringErr, logger);
};

const reopenReadOnlyAfterMissingShadow = async (
  dbPath: string,
  err: unknown,
): Promise<LbugConnectionHandle> => {
  await refuseLargeWalQuarantine(dbPath, 'read-only', err);
  try {
    await quarantineWalForMissingShadow(dbPath, {
      logger,
      level: 'warn',
      reason: 'read-only recovery',
    });
  } catch (renameErr) {
    throw new Error(renameFailureMessage(dbPath, renameErr));
  }

  const reopened = await openLbugConnection(lbug, dbPath, { readOnly: true });
  try {
    await queryAndDrain(reopened.conn, READ_ONLY_SHADOW_REPLAY_PROBE);
    return reopened;
  } catch (retryErr) {
    await closeLbugConnection(reopened);
    if (isMissingShadowSidecarError(retryErr) || isReadOnlyShadowReplayError(retryErr)) {
      throw new Error(shadowSidecarRecoveryMessage(dbPath, retryErr));
    }
    throw retryErr;
  }
};

const reopenWritableAfterMissingShadow = async (
  dbPath: string,
  err: unknown,

View on GitHub (pinned to d540b00184)

Solutions

  1. Stop any GitNexus MCP or serve process using this repository, then re-run the failing command.
  2. Add an antivirus exclusion for the GitNexus storage directory (`.gitnexus/`).
  3. Fix filesystem permissions/ACLs on the storage directory so the rename can succeed.
  4. The index does NOT need to be rebuilt for the permission/lock class — re-run after the lock clears.
Defensive patterns

Strategy: try-catch

Type guard

function isWalRenameLockError(err): boolean {
  return /could not move the LadybugDB WAL sidecar.*permission or file-lock/i.test(
    err instanceof Error ? err.message : String(err),
  );
}

Try / catch

try {
  await openReadOnly(dbPath);
} catch (err) {
  if (/WAL sidecar.*permission or file-lock/i.test(err.message)) {
    // Stop other gitnexus processes / add AV exclusion, then re-run.
    // No rebuild needed for this class.
    console.error(err.message);
    process.exit(6);
  }
  throw err;
}

Prevention

When it happens

Trigger: `quarantineWalForMissingShadow` calls `fs.rename` on the `.wal` file and the OS rejects it with EACCES/EPERM/EBUSY during a read-only reopen attempt. Typically an antivirus scan or another gitnexus process holds an open handle on the WAL.

Common situations: Windows antivirus locking the `.wal` during a scan; a lingering `gitnexus serve`/MCP process holding the index; a read-only container mount that also denies the rename; ACLs on the storage directory.

Related errors


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