{"record":{"id":"60fb2deb1a89c075","repo":"abhigyanpatwari/GitNexus","slug":"gitnexus-unable-to-inspect-init-lock-code","errorCode":null,"errorMessage":"GitNexus: unable to inspect init lock (${code ?? 'UNKNOWN'}): ${summarizeError(err)}","messagePattern":"GitNexus: unable to inspect init lock \\((.+?)\\): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"gitnexus/src/core/lbug/lbug-adapter.ts","lineNumber":378,"sourceCode":"      // (e.g. the process is hung). Check the timestamp.\n      if (typeof parsed.ts === 'number' && Date.now() - parsed.ts < INIT_LOCK_STALE_MS) {\n        return false;\n      }\n    }\n\n    // PID is gone or lock exceeded INIT_LOCK_STALE_MS — reclaim it.\n    await fs.unlink(lockPath);\n    logger.warn(\n      `GitNexus: removed stale init lock (pid=${parsed.pid ?? '?'}, age=${typeof parsed.ts === 'number' ? `${Date.now() - parsed.ts}ms` : '?'})`,\n    );\n    return true;\n  } catch (err) {\n    // Lock file disappeared between our read and unlink, or is unreadable.\n    // Either way, let the caller retry the acquire.\n    if (isMissingFileError(err)) return true;\n    // Permission error or corrupt content — log and let caller retry.\n    const code = extractErrnoCode(err);\n    logger.warn(\n      `GitNexus: unable to inspect init lock (${code ?? 'UNKNOWN'}): ${summarizeError(err)}`,\n    );\n    return false;\n  }\n};\n\n/**\n * Acquire a cross-process init lock for `dbPath`.\n * Uses `O_CREAT | O_EXCL` for atomic create-or-fail semantics.\n *\n * Returns a release function that removes the lock file. The release\n * function is idempotent and safe to call even if the lock was already\n * cleaned up externally.\n *\n * Throws if the lock cannot be acquired after `INIT_LOCK_MAX_ATTEMPTS`.\n */\nexport const acquireInitLock = async (dbPath: string): Promise<() => Promise<void>> => {\n  const lockPath = initLockPath(dbPath);","sourceCodeStart":360,"sourceCodeEnd":396,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/aac7515d2a8c50a1f8f923c6fb77218b333560d6/gitnexus/src/core/lbug/lbug-adapter.ts#L360-L396","documentation":"Thrown during tryBreakStaleLock while deciding whether an existing init lock file (O_CREAT|O_EXCL) can be reclaimed. The function read the lock, found the PID gone or the lock older than INIT_LOCK_STALE_MS, but then hit a non-ENOENT filesystem error (EACCES/EPERM, EIO, unparsable content path). It returns false, meaning 'do not break it; let the caller retry the acquire loop' rather than deleting a lock it cannot inspect.","triggerScenarios":"initLbug(dbPath) is called while a lock file exists at `${dbPath}.init.lock`-style path; tryBreakStaleLock's fs operations fail with EACCES (lock created by another user/root), EIO, or the unlink races in a way that is not ENOENT. The acquire loop then retries, so the caller may loop until the situation changes.","commonSituations":"Indexing the same repo as root and then as a normal user (or vice versa); lock files on NFS/network mounts with permission quirks; containers sharing a volume with differing UIDs; security software briefly locking files mid-inspect.","solutions":["Inspect the lock file next to the DB path: `ls -l <dbPath>*lock*` and check owner/permissions; chown/chmod it so the current user can read and unlink it.","If no other gitnexus process is running, delete the stale lock file manually and retry the operation.","Ensure only one user/context (same UID) runs `analyze`/`serve` against the same .gitnexus database directory.","Retry the command — the acquire loop tolerates transient races and the warn is non-fatal."],"exampleFix":"# before: analyze fails to acquire, warns 'unable to inspect init lock (EACCES)'\nls -la .gitnexus/*.lock   # shows root-owned lock from an earlier sudo run\n\n# after\nsudo rm .gitnexus/*.lock && gitnexus analyze","handlingStrategy":"retry","validationCode":"// Before initLbug: assert the lock file is readable/unlinkable by this user\nimport { access, constants } from 'node:fs/promises';\ntry {\n  await access(lockPath, constants.R_OK | constants.W_OK);\n} catch {\n  // unreadable lock: fix ownership now instead of looping the acquire retry\n  throw new Error(`init lock ${lockPath} not accessible by uid=${process.getuid?.()}`);\n}","typeGuard":null,"tryCatchPattern":"// tryBreakStaleLock returns boolean: false means 'could not inspect, retry acquire'\nif (!(await tryBreakStaleLock(lockPath))) {\n  await sleep(backoffMs);\n  continue; // retry the O_EXCL acquire; give up after N attempts with a clear error\n}","preventionTips":["Run all gitnexus commands against one repo as the same OS user.","Keep the .gitnexus directory off permission-quirky network mounts.","Clean up lock files when tearing down containers that share volumes."],"tags":["file-lock","permissions","ladybugdb","concurrency","init"],"backgroundTag":"lock-file-permission-denied","analyzedSha":"aac7515d2a8c50a1f8f923c6fb77218b333560d6","analyzedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}