JuliusBrussee/caveman · error · Error
cave_stale_lock:registration
Error message
cave_stale_lock:registration
What it means
Before registering, the CLI re-validates .caveman/agent.lock.json against freshly loaded build inputs: validLockIdentity(root, entry) must succeed AND its build_sha256 must equal the one in the lock read earlier. Failure means the lock is stale relative to current sources/config — registering it would publish a build hash that no longer matches the code, so registration is refused with the cave_stale_lock:registration scope tag.
Source
Thrown at packages/agent/src/cli.ts:475
available: Boolean(process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY),
};
}
return { name: `credential for ${provider || "unknown provider"}`, available: false };
}
async function register(_args: string[]): Promise<void> {
const root = process.cwd();
const controlURL = process.env.CAVE_CONTROL_URL?.replace(/\/+$/, "");
const token = process.env.CAVE_TOKEN ?? process.env.CAVE_API_TOKEN;
const projectID = process.env.CAVE_PROJECT_ID;
if (!controlURL || !token || !projectID) {
throw new Error("register requires CAVE_CONTROL_URL, CAVE_TOKEN, and CAVE_PROJECT_ID");
}
const lock = await readLock(root);
const loaded = await loadBuildInputs(root, "caveman.config.ts");
const checked = await validLockIdentity(root, loaded.config.entry);
if (!checked || checked.build_sha256 !== lock.build_sha256) {
throw new Error("cave_stale_lock:registration");
}
const response = await fetch(`${controlURL}/api/v1/projects/${encodeURIComponent(projectID)}/agent-builds`, {
method: "POST",
headers: {
authorization: `Bearer ${token}`,
"content-type": "application/json",
},
body: JSON.stringify({
agent_slug: lock.agent_id,
build_sha256: lock.build_sha256,
plan_sha256: lock.plan_sha256,
source_sha256: lock.source_sha256,
eval_suite_sha256: lock.eval_suite_sha256,
catalog_sha256: lock.catalog_sha256,
transform_registry_sha256: lock.runtime.transform_registry_sha256,
harness: lock.harness.id,
adapter_version: lock.harness.adapter_version,
upstream_version: lock.harness.upstream_version,View on GitHub (pinned to 27d5a3981a)
Solutions
- Rebuild to refresh the lock: caveman-agent build, then caveman-agent register.
- If register keeps failing, run caveman-agent doctor to see the lock check state and confirm which inputs drifted.
- Treat the lock as an artifact: commit it at the same commit as the sources it hashes, and never edit sources between build and register.
Example fix
# before caveman-agent build # (edit src/agent.ts) caveman-agent register # throws cave_stale_lock:registration # after caveman-agent build caveman-agent register # no edits in between
Defensive patterns
Strategy: validation
Validate before calling
async function lockMatchesCurrentBuild(root: string): Promise<boolean> {
const loaded = await loadBuildInputs(root, "caveman.config.ts");
const lock = await readLock(root);
const checked = await validLockIdentity(root, loaded.config.entry);
return Boolean(checked) && checked.build_sha256 === lock.build_sha256;
} Try / catch
try {
await register(args);
} catch (error) {
if (error instanceof Error && error.message === "cave_stale_lock:registration") {
// deterministic fix: rebuild to refresh the lock, then register once
await build(["caveman.config.ts"]);
return register(args);
}
throw error;
} Prevention
- Run build and register back-to-back in one CI job with no source edits in between.
- Commit .caveman/agent.lock.json in the same commit as the sources it hashes.
- If register keeps failing after a fresh build, run doctor to identify which build input keeps drifting.
When it happens
Trigger: Editing any build input (entry, caveman.config.ts, eval files, source graph) after `caveman-agent build` and then running register; no lock at all (validLockIdentity falsy); or the lock being regenerated between readLock and validation (sha mismatch).
Common situations: Build → commit/push → teammate pulls → sources move ahead of the committed lock; CI checkout where .caveman/agent.lock.json is cached but the repo advanced; local hotfix edit forgotten before register.
Related errors
- lock disappeared during validation
- register requires CAVE_CONTROL_URL, CAVE_TOKEN, and CAVE_PRO
- registration failed: HTTP ${response.status}
- cave_build_lock_missing: approve required evals, then run np
- cave_stale_lock:${checked.stale.join(",")}: run npm run buil
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/34db8fa45ef6ad61.
Report an issue: GitHub.