abhigyanpatwari/GitNexus · error
The LadybugDB graph store at
Error message
The LadybugDB graph store at ${lbugPath} is not a usable database file. Run gitnexus analyze first. What it means
The LadybugDB path exists but lstat shows it is not a regular file (e.g. a directory, symlink to nothing handled elsewhere, or other special file), so it cannot be used as the graph database. Sync refuses to operate on unusable database paths.
Solutions
- Inspect the reported path: `ls -la <lbugPath>`; remove/rename the directory or invalid entry that occupies the DB filename.
- Run `gitnexus analyze` to recreate a valid database file, then re-run sync.
- Fix any mount/volume configuration that substitutes a directory at the database path.
- Do not hand-create files/dirs under the index storage directory.
Example fix
// before $ ls -la .gitnexus/index.lbug # drwxr-xr-x (directory!) // after $ rm -rf .gitnexus/index.lbug $ gitnexus analyze $ gitnexus embeddings-sync .
Defensive patterns
Strategy: validation
Validate before calling
import { existsSync, lstatSync } from 'node:fs';
function dbPathIsFile(p) {
try { return lstatSync(p).isFile(); } catch { return false; }
}
// if the DB path is a directory or special file, rebuild instead of syncing
if (!dbPathIsExpectedFile) { /* rm the bad entry, then gitnexus analyze */ } Try / catch
try {
await gitnexus.embeddingsSync(repo);
} catch (err) {
if (err.message.includes('not a usable database file')) {
// remove/fix the invalid entry at the reported path, then:
await run('gitnexus analyze');
await gitnexus.embeddingsSync(repo);
} else throw err;
} Prevention
- Never create files or directories inside the index storage directory by hand.
- Check Docker/Kubernetes volume mount targets don't shadow the DB file with a directory.
- Inspect storage paths with `ls -la` after any storage reconfiguration.
- Keep backup tooling from replacing index files with placeholders.
When it happens
Trigger: The expected database path is a directory (someone created a folder with the DB's name), a corrupted placeholder, a broken special file, or a symlink resolving to a non-file.
Common situations: Docker volume mounts replacing the DB path with a directory; a misconfigured storage path colliding with an existing directory; backup tools substituting placeholders.
Related errors
- The LadybugDB graph store at
- Cannot sync embeddings: the index checkpoint was written by
- [embed] could not count persisted embeddings; leaving…
- [embed] Failed to delete stale embedding rows — aborting to…
- No GitNexus index found for
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15).
Data as JSON: /api/errors/09f6dbed8a5c6134.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/cli/embeddings-sync.ts:70
`Cannot acquire the index lock at ${metaDir}; refusing an unlocked embeddings sync.`,
);
const meta = await loadMeta(metaDir);
if (!meta)
throw new Error(`No GitNexus index found for ${repoPath}. Run gitnexus analyze first.`);
if (meta.incrementalInProgress) {
throw new Error('The structural index is incomplete. Run gitnexus analyze --force first.');
}
let lbugStat;
try {
lbugStat = await lstat(lbugPath);
} catch {
throw new Error(
`The LadybugDB graph store at ${lbugPath} is missing. Run gitnexus analyze first.`,
);
}
if (!lbugStat.isFile()) {
throw new Error(
`The LadybugDB graph store at ${lbugPath} is not a usable database file. Run gitnexus analyze first.`,
);
}
const { resolveEmbeddingIdentity } = await import('../core/embeddings/embedding-identity.js');
const identity = resolveEmbeddingIdentity();
let forceReembedNodeIds: ReadonlySet<string> | undefined;
let resumedFrom: EmbeddingCheckpoint | undefined;
if (meta.embeddingCheckpoint) {
const checkpoint = meta.embeddingCheckpoint;
const decision = decideEmbeddingResume(checkpoint, identity);
if (decision.action === 'abort') throw new Error(decision.error);
const identityDiffers =
checkpoint.provider !== identity.provider ||
checkpoint.model !== identity.model ||
checkpoint.dimensions !== identity.dimensions;
// `abandon` on a foreign identity drops the pending set only. Existing
// rows stay; sync would then embed the holes under the new identity andView on GitHub (pinned to ac9a4e9abd)