abhigyanpatwari/GitNexus · warning

GitNexus: unable to inspect init lock (${code ?? 'UNKNOWN'})

Error message

GitNexus: unable to inspect init lock (${code ?? 'UNKNOWN'}): ${summarizeError(err)}

What it means

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.

Source

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

      // (e.g. the process is hung). Check the timestamp.
      if (typeof parsed.ts === 'number' && Date.now() - parsed.ts < INIT_LOCK_STALE_MS) {
        return false;
      }
    }

    // PID is gone or lock exceeded INIT_LOCK_STALE_MS — reclaim it.
    await fs.unlink(lockPath);
    logger.warn(
      `GitNexus: removed stale init lock (pid=${parsed.pid ?? '?'}, age=${typeof parsed.ts === 'number' ? `${Date.now() - parsed.ts}ms` : '?'})`,
    );
    return true;
  } catch (err) {
    // Lock file disappeared between our read and unlink, or is unreadable.
    // Either way, let the caller retry the acquire.
    if (isMissingFileError(err)) return true;
    // Permission error or corrupt content — log and let caller retry.
    const code = extractErrnoCode(err);
    logger.warn(
      `GitNexus: unable to inspect init lock (${code ?? 'UNKNOWN'}): ${summarizeError(err)}`,
    );
    return false;
  }
};

/**
 * Acquire a cross-process init lock for `dbPath`.
 * Uses `O_CREAT | O_EXCL` for atomic create-or-fail semantics.
 *
 * Returns a release function that removes the lock file. The release
 * function is idempotent and safe to call even if the lock was already
 * cleaned up externally.
 *
 * Throws if the lock cannot be acquired after `INIT_LOCK_MAX_ATTEMPTS`.
 */
export const acquireInitLock = async (dbPath: string): Promise<() => Promise<void>> => {
  const lockPath = initLockPath(dbPath);

View on GitHub (pinned to aac7515d2a)

Solutions

  1. 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.
  2. If no other gitnexus process is running, delete the stale lock file manually and retry the operation.
  3. Ensure only one user/context (same UID) runs `analyze`/`serve` against the same .gitnexus database directory.
  4. Retry the command — the acquire loop tolerates transient races and the warn is non-fatal.

Example fix

# before: analyze fails to acquire, warns 'unable to inspect init lock (EACCES)'
ls -la .gitnexus/*.lock   # shows root-owned lock from an earlier sudo run

# after
sudo rm .gitnexus/*.lock && gitnexus analyze
Defensive patterns

Strategy: retry

Validate before calling

// Before initLbug: assert the lock file is readable/unlinkable by this user
import { access, constants } from 'node:fs/promises';
try {
  await access(lockPath, constants.R_OK | constants.W_OK);
} catch {
  // unreadable lock: fix ownership now instead of looping the acquire retry
  throw new Error(`init lock ${lockPath} not accessible by uid=${process.getuid?.()}`);
}

Try / catch

// tryBreakStaleLock returns boolean: false means 'could not inspect, retry acquire'
if (!(await tryBreakStaleLock(lockPath))) {
  await sleep(backoffMs);
  continue; // retry the O_EXCL acquire; give up after N attempts with a clear error
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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