{"record":{"id":"b2a249c941593039","repo":"JuliusBrussee/caveman","slug":"lock-disappeared-during-validation","errorCode":null,"errorMessage":"lock disappeared during validation","messagePattern":"lock disappeared during validation","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/agent/src/cli.ts","lineNumber":231,"sourceCode":"      status: \"warn\",\n      detail: `gateway not reachable at ${gatewayURL} — telemetry off, runs are observe-only`,\n      fix: \"npm i -g @caveman-ai/cli && caveman start\",\n    });\n\n  const configPath = resolve(root, \"caveman.config.ts\");\n  try {\n    await readFile(configPath);\n    const loaded = await loadBuildInputs(root, \"caveman.config.ts\");\n    await lowerBuildContext(root, loaded.agent);\n    checks.push({\n      id: \"project\",\n      status: \"pass\",\n      detail: `${loaded.agent.id}: config, entry, eval graph, and static Context IR load`,\n    });\n    try {\n      await readFile(resolve(root, \".caveman/agent.lock.json\"));\n      const lock = await validLockIdentity(root, loaded.config.entry, loaded.agent);\n      if (!lock) throw new Error(\"lock disappeared during validation\");\n      checks.push({\n        id: \"lock\",\n        status: \"pass\",\n        detail: `${lock.harness.id} build ${lock.build_sha256.slice(0, 12)} is current`,\n      });\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n        checks.push({\n          id: \"lock\",\n          status: \"warn\",\n          detail: \"no Cave Build lock; dev runs unlocked\",\n          fix: \"approve required evals, then run caveman-agent build\",\n        });\n      } else {\n        checks.push({\n          id: \"lock\",\n          status: \"fail\",\n          detail: safeDiagnostic(error),","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/cli.ts#L213-L249","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-run `caveman-agent doctor` — a transient race usually passes on the second attempt with no concurrent writers.","Ensure only one caveman-agent process (build/dev/register) runs per repo at a time.","If it persists, regenerate the lock: caveman-agent build, then doctor again; check git status for .caveman churn."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"async function lockStable(root: string): Promise<boolean> {\n  const a = await readFile(join(root, \".caveman\", \"agent.lock.json\"), \"utf8\").catch(() => null);\n  await new Promise((r) => setTimeout(r, 50));\n  const b = await readFile(join(root, \".caveman\", \"agent.lock.json\"), \"utf8\").catch(() => null);\n  return a !== null && a === b;\n}","typeGuard":null,"tryCatchPattern":"let attempts = 0;\nwhile (true) {\n  try {\n    return await doctor(args);\n  } catch (error) {\n    if (error instanceof Error && error.message === \"lock disappeared during validation\" && ++attempts < 3) {\n      continue; // concurrent writer raced us; retry after it settles\n    }\n    throw error;\n  }\n}","preventionTips":["Serialize caveman-agent invocations per repo (only one build/dev/register/doctor at a time).","Exclude .caveman/ from sync tools and auto-formatters that rewrite files asynchronously.","Treat recurrence after a clean retry as a genuinely invalid lock: rebuild it with caveman-agent build."],"tags":["doctor","race-condition","lock","filesystem"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}