JuliusBrussee/caveman · warning · Error

lock disappeared during validation

Error message

lock disappeared during validation

What it means

During doctor's lock check, .caveman/agent.lock.json was readable a moment ago (readFile succeeded) but validLockIdentity() then returned falsy — the lock no longer validates against the current entry/agent identity. The message 'lock disappeared during validation' describes a race or a lock whose content fails identity validation while existing on disk.

Source

Thrown at packages/agent/src/cli.ts:231

      status: "warn",
      detail: `gateway not reachable at ${gatewayURL} — telemetry off, runs are observe-only`,
      fix: "npm i -g @caveman-ai/cli && caveman start",
    });

  const configPath = resolve(root, "caveman.config.ts");
  try {
    await readFile(configPath);
    const loaded = await loadBuildInputs(root, "caveman.config.ts");
    await lowerBuildContext(root, loaded.agent);
    checks.push({
      id: "project",
      status: "pass",
      detail: `${loaded.agent.id}: config, entry, eval graph, and static Context IR load`,
    });
    try {
      await readFile(resolve(root, ".caveman/agent.lock.json"));
      const lock = await validLockIdentity(root, loaded.config.entry, loaded.agent);
      if (!lock) throw new Error("lock disappeared during validation");
      checks.push({
        id: "lock",
        status: "pass",
        detail: `${lock.harness.id} build ${lock.build_sha256.slice(0, 12)} is current`,
      });
    } catch (error) {
      if ((error as NodeJS.ErrnoException).code === "ENOENT") {
        checks.push({
          id: "lock",
          status: "warn",
          detail: "no Cave Build lock; dev runs unlocked",
          fix: "approve required evals, then run caveman-agent build",
        });
      } else {
        checks.push({
          id: "lock",
          status: "fail",
          detail: safeDiagnostic(error),

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Re-run `caveman-agent doctor` — a transient race usually passes on the second attempt with no concurrent writers.
  2. Ensure only one caveman-agent process (build/dev/register) runs per repo at a time.
  3. If it persists, regenerate the lock: caveman-agent build, then doctor again; check git status for .caveman churn.
Defensive patterns

Strategy: retry

Validate before calling

async function lockStable(root: string): Promise<boolean> {
  const a = await readFile(join(root, ".caveman", "agent.lock.json"), "utf8").catch(() => null);
  await new Promise((r) => setTimeout(r, 50));
  const b = await readFile(join(root, ".caveman", "agent.lock.json"), "utf8").catch(() => null);
  return a !== null && a === b;
}

Try / catch

let attempts = 0;
while (true) {
  try {
    return await doctor(args);
  } catch (error) {
    if (error instanceof Error && error.message === "lock disappeared during validation" && ++attempts < 3) {
      continue; // concurrent writer raced us; retry after it settles
    }
    throw error;
  }
}

Prevention

When it happens

Trigger: The lock file is deleted or rewritten between the readFile and validLockIdentity call (concurrent caveman-agent build/dev/register, editor save, git checkout switching branches); or validLockIdentity rejects the lock (stale build hash vs entry/config) in a way that surfaces through this throw.

Common situations: Two terminals running build/doctor concurrently on the same repo; git operations swapping .caveman/agent.lock.json mid-diagnostic; watchdog/sync tool (Dropbox, IDE auto-format) touching the file.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/b2a249c941593039. Report an issue: GitHub.