{"record":{"id":"1864dd2fac8d9277","repo":"JuliusBrussee/caveman","slug":"cave-stale-lock-entry","errorCode":null,"errorMessage":"cave_stale_lock:entry","messagePattern":"cave_stale_lock:entry","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/cli.ts","lineNumber":1053,"sourceCode":"    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n    }\n  }\n  const sourceSha256 = await sourceGraphSHA256(root, sourceFiles);\n  return { config, agent, evals, sourceSha256 };\n}\n\nasync function validLockIdentity(\n  root: string,\n  entry: string,\n  expectedAgent?: AgentDefinition,\n  beforeSourceHash?: Parameters<typeof loadBuildInputs>[2],\n): Promise<CaveBuildLock | undefined> {\n  try {\n    const lock = await readLock(root);\n    const loaded = await loadBuildInputs(root, \"caveman.config.ts\", beforeSourceHash);\n    if (resolve(root, loaded.config.entry) !== resolve(root, entry)) {\n      throw new Error(\"cave_stale_lock:entry\");\n    }\n    if (expectedAgent !== undefined &&\n        agentDefinitionSHA256(loaded.agent) !== agentDefinitionSHA256(expectedAgent)) {\n      throw new Error(\"cave_stale_lock:dev_snapshot\");\n    }\n    const checked = checkLock(lock, {\n      sourceSha256: loaded.sourceSha256,\n      agentDefinitionSha256: agentDefinitionSHA256(loaded.agent),\n      contextIRSha256: contextIRSHA256(await lowerBuildContext(\n        root,\n        loaded.agent,\n      ).then((value) => value.ir)),\n      evalSuiteSha256: sha256(stableStringify(loaded.evals.filter((item) => item.approved && item.required))),\n      runtimeVersion: FRAMEWORK_VERSION,\n      adapterVersion: PI_ADAPTER_VERSION,\n      upstreamVersion: PI_UPSTREAM_VERSION,\n      transformRegistrySha256: await transformRegistrySHA256(),\n      catalogSha256: CATALOG_SHA256,","sourceCodeStart":1035,"sourceCodeEnd":1071,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/766dce6b1394ebb56a3090748d5a0240a5aefb36/packages/agent/src/cli.ts#L1035-L1071","documentation":"`validLockIdentity` (the dev/locked identity path) reads the lock, reloads caveman.config.ts, and requires the config's `entry` to resolve to the same absolute file as the `entry` argument the caller passed. `cave_stale_lock:entry` means the lock on disk was built from a different entry module than the one now being run, so the lock's digests describe another agent.","triggerScenarios":"Running `caveman dev src/agent-v2.ts` while caveman.config.ts still declares `entry: \"src/agent.ts\"`; renaming the entry file without updating the config and rebuilding; pointing the CLI at a differently-spelled path that resolves to a different file.","commonSituations":"A refactor renames the entry module; two agents share one repo and the lock was built for the other; a lock file copied from another project.","solutions":["Invoke the entry that caveman.config.ts declares (or update `entry` in caveman.config.ts and run `npm run build`)","Run `npm run build` to relock against the current config entry","If `.caveman/agent.lock.json` came from another project, delete it and rebuild"],"exampleFix":"# before: lock was built with entry \"src/agent.ts\"\ncaveman dev src/agent-v2.ts   # → cave_stale_lock:entry\n# after: align config and relock\n#   caveman.config.ts: entry: \"src/agent-v2.ts\"\nnpm run build && caveman dev src/agent-v2.ts","handlingStrategy":"validation","validationCode":"import { resolve } from \"node:path\";\nconst { default: config } = await import(\"./caveman.config.ts\");\nconst entryArg = process.argv[2];\nif (entryArg && resolve(root, config.entry) !== resolve(root, entryArg)) {\n  throw new Error(`invoke the locked entry (${config.entry}) or update the config and run npm run build`);\n}","typeGuard":null,"tryCatchPattern":"catch (e) { if (e instanceof Error && e.message === \"cave_stale_lock:entry\") { /* align entry arg with caveman.config.ts entry, then npm run build */ } else throw e; }","preventionTips":["Always invoke dev with the same entry string caveman.config.ts declares","Rename the entry in config and rebuild in the same commit","Never copy .caveman/agent.lock.json between projects"],"tags":["build-lock","entry-mismatch","dev","drift"],"backgroundTag":"stale-build-artifact","analyzedSha":"766dce6b1394ebb56a3090748d5a0240a5aefb36","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}