JuliusBrussee/caveman · error
cave_stale_lock
cave_stale_lock
Error message
cave_stale_lock:registration
What it means
`register` verifies that the on-disk build lock still matches the current build inputs before uploading it. It loads the config, runs validLockIdentity over the entry, and compares the resulting build_sha256 with the lock's. If the identity check fails (no valid lock identity) or the hashes differ, the lock is stale and registration is refused with this coded error.
Solutions
- Run `npm run build` (the caveman build command) to regenerate the lock.
- Re-run `caveman register` after the fresh build.
- If inputs should not have changed, `git status`/`git diff` to find and revert accidental edits made after the build.
- Verify the lock file exists and was produced by the same commit you are registering.
Example fix
// before caveman register # throws cave_stale_lock:registration // after npm run build && caveman register
Defensive patterns
Strategy: retry
Validate before calling
// after any source/config change, rebuild first await run(["npm", "run", "build"]); // then register await run(["npx", "caveman", "register"]);
Try / catch
try {
await register();
} catch (err) {
if (String(err?.message).startsWith("cave_stale_lock")) {
await run(["npm", "run", "build"]); // relock
await register(); // retry once
} else throw err;
} Prevention
- Always rebuild (npm run build) after editing source, evals, or config before registering.
- Automate register behind the build target so ordering is guaranteed.
- Avoid hand-editing generated lock files.
- Pin dependency versions so hashes don't drift unexpectedly.
When it happens
Trigger: Calling `caveman register` after source, config, evals, or dependency versions changed since the last `npm run build`, so validLockIdentity returns null or a build_sha256 different from the lock's; or the lock file is missing/malformed.
Common situations: Editing agent source or caveman.config.ts after building and then registering without rebuilding; a teammate bumped a dependency that changes the transform registry hash; registering a CI artifact built from a different commit.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- adapter-specific build_sha256 values must differ
- caveman-cloud MCP changed after setup; refusing destructive…
- caveman-cloud MCP changed during interrupted setup…
- caveman-cloud MCP changed during interrupted removal…
- caveman-cloud MCP postflight mismatch
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/4f86f516ea0cede0.
Report an issue: GitHub.
Appendix: 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 3ee70a1026)