abhigyanpatwari/GitNexus · error
GitNexus: unable to acquire init lock after
Error message
GitNexus: unable to acquire init lock after ${INIT_LOCK_MAX_ATTEMPTS} attempts — another gitnexus process may be initializing the same database (${lockPath}) What it means
The init lock in lbug-adapter.ts serializes database initialization with an exclusive lock file: up to INIT_LOCK_MAX_ATTEMPTS (6) attempts spaced INIT_LOCK_RETRY_DELAY_MS (500ms) apart, breaking stale locks between attempts. If a live process still holds the lock after ~3 seconds, this error reports that another GitNexus process is probably initializing the same database, naming the lock path.
Solutions
- Wait for the in-flight process to finish initializing, then re-run the command
- Stop the concurrent process (gitnexus serve / MCP server) that holds the lock, then retry
- If you can verify no other GitNexus process is running, remove the lock file at the path named in the message
- Serialize writers: ensure only one process initializes a given database at a time (one analyze, or one serve, per repo/storage dir)
Example fix
# before: two processes race $ gitnexus serve & gitnexus analyze . # after: stop the server first, then initialize $ gitnexus mcp stop # or kill the serve process gitnexus analyze . gitnexus serve &
Defensive patterns
Strategy: retry
Validate before calling
import fs from 'node:fs';
const lockPath = getLockPath(dbPath); // same path the adapter names in the error
try {
fs.accessSync(lockPath);
console.error(`Init lock present at ${lockPath} — another gitnexus process may be initializing; wait or stop it.`);
process.exit(1);
} catch {
/* no lock — safe to proceed */
}
await openDatabase(dbPath); Try / catch
try {
await withLbugDb(dbPath, run);
} catch (err) {
if (err instanceof Error && err.message.includes('unable to acquire init lock')) {
// wait for the concurrent initializer to finish (or stop it), verify no gitnexus process runs,
// optionally delete the lock file named in the message, then retry once
}
throw err;
} Prevention
- Serialize database initialization per storage dir: one writer (analyze or serve/MCP) at a time
- In CI, guard shared index volumes with a job-level mutex so matrix jobs don't race the init lock
- If a run was killed, check for and clear leftover lock files before the next run
When it happens
Trigger: Running `gitnexus analyze` (or any DB-opening command) concurrently with a `gitnexus serve`/MCP process that is initializing the same index; two CLI invocations racing on a shared GITNEXUS_HOME storage dir; parallel CI jobs sharing a cache volume; or a leftover lock file that tryBreakStaleLock did not consider stale.
Common situations: IDE MCP server auto-starting while the user runs the CLI on the same repo; CI matrix jobs sharing an index volume; a previous crash leaving a lock whose PID/heuristics still look live.
Related errors
- GitNexus: unable to inspect init lock
- Failed to remove the LadybugDB index files — still present…
- GitNexus could not move the LadybugDB WAL sidecar at
- GitNexus: failed to release init lock
- GitNexus: manual WAL checkpoint failed after retries
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-08-20).
Data as JSON: /api/errors/56d2cda559f9234a.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/core/lbug/lbug-adapter.ts:431
logger.warn(
`GitNexus: failed to release init lock (${code ?? 'UNKNOWN'}): ${summarizeError(err)}`,
);
}
}
};
} catch (err) {
if ((err as NodeJS.ErrnoException)?.code !== 'EEXIST') {
throw err; // Unexpected error — propagate immediately
}
// Lock file exists — check if it's stale
const broken = await tryBreakStaleLock(lockPath);
if (broken && attempt < INIT_LOCK_MAX_ATTEMPTS) {
continue; // Stale lock removed — retry immediately
}
if (attempt === INIT_LOCK_MAX_ATTEMPTS) {
throw new Error(
`GitNexus: unable to acquire init lock after ${INIT_LOCK_MAX_ATTEMPTS} attempts — ` +
`another gitnexus process may be initializing the same database (${lockPath})`,
);
}
// Live process holds the lock — wait and retry
await new Promise((resolve) => setTimeout(resolve, INIT_LOCK_RETRY_DELAY_MS));
}
}
// Unreachable — loop always throws or returns
throw new Error('GitNexus: init lock acquisition failed unexpectedly');
};
/** Exported for testing — returns the lock file path for a given dbPath. */
export const _initLockPathForTest = initLockPath;
const runWithSessionLock = async <T>(operation: () => Promise<T>): Promise<T> => {View on GitHub (pinned to ac9a4e9abd)