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
- 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.
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
- 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.
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
- Cave Build lock changed during validation; refusing Claude l
- cave_harness_aborted
- cave_vercel_terminal_failure
- caveman agent: invalid .caveman/provider.json
- usage: caveman-agent doctor [--json]
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/b2a249c941593039.
Report an issue: GitHub.