JuliusBrussee/caveman · error · Error
cave_harness_context_ir_mismatch
cave_harness_context_ir_mismatch
Error message
cave_harness_context_ir_mismatch
What it means
Thrown while preparing a locked harness (packages/agent/src/execution-kernel.ts:90): the SHA-256 of the wire-form Context IR supplied at run time does not match context_ir_sha256 in the CaveBuildLock. The lock pins the static context segments of the agent definition; if the lowered context IR changed after the lock was built, execution fails closed before any provider traffic.
Source
Thrown at packages/agent/src/execution-kernel.ts:90
const build = parseCaveBuildLock(input.build);
if (build.harness.id !== input.harness ||
build.harness.adapter_version !== input.adapterVersion ||
build.harness.upstream_version !== input.upstreamVersion) {
throw new Error("cave_harness_build_mismatch");
}
if (input.agentId !== undefined && build.agent_id !== input.agentId) {
throw new Error("cave_harness_agent_mismatch");
}
if (stableStringify(input.plan) !== stableStringify(build.selected_plan)) {
throw new Error("cave_harness_plan_mismatch");
}
const planSHA256 = sha256(stableStringify(input.plan));
if (planSHA256 !== build.plan_sha256) {
throw new Error("cave_harness_plan_digest_mismatch");
}
const contextIRSHA256 = sha256(stableStringify(contextIRToWire(input.contextIR)));
if (contextIRSHA256 !== build.context_ir_sha256) {
throw new Error("cave_harness_context_ir_mismatch");
}
const [provider, ...modelParts] = input.plan.model.split("/");
const model = modelParts.join("/");
if (!provider || !model) throw new Error("cave_harness_model_invalid");
return Object.freeze({
build,
plan: build.selected_plan,
planSHA256,
contextIRSHA256,
provider,
model,
});
}
export interface ProviderUsageEvidence {
provider: string;
model: string;
inputTokens: number;View on GitHub (pinned to 27d5a3981a)
Solutions
- Rebuild the lock after any change to instructions, contexts, tools, or other static definition segments.
- Confirm the file sources feeding the Context IR are unchanged since the build (FileSource contents are part of static segments).
- After a framework upgrade, regenerate all locks — lowered IR shape may change between versions.
Example fix
# before # edit prompts/system.md, then run with the old lock caveman run --lock cave-build.lock # -> cave_harness_context_ir_mismatch # after caveman build && caveman run --lock cave-build.lock
Defensive patterns
Strategy: validation
Validate before calling
// Before running a locked build, recompute the Context IR digest:
const irDigest = sha256(stableStringify(contextIRToWire(lowerContextIR(definition))));
if (irDigest !== lock.context_ir_sha256) {
await rebuildLock(); // static definition segments changed since build
} Prevention
- Rebuild the lock after any edit to instructions, contexts, tools, or FileSource contents.
- Remember runtime segments (user input, history, tool results) never affect this digest — only static definition content does.
- Automate lock regeneration in dev watch flows so prompt edits don't leave stale locks.
When it happens
Trigger: Changing an agent's instructions, contexts, tool definitions, or other static segments after the lock was generated, then running with the old lock; anything that alters contextIRToWire output (definition edits, framework upgrade changing lowering).
Common situations: Editing prompts/context files or the agent definition and forgetting to rebuild; upgrading @caveman-ai/agent so the Context IR lowering changed shape; note eval/user input, history, and tool results are runtime segments and never enter this digest — so the drift is always in static definition content.
Related errors
- cave_harness_plan_mismatch
- cave_harness_build_mismatch
- cave_privacy_conformance_failed
- cave_context_body_missing:${segment.id}
- 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/f0dc4542e81fbf53.
Report an issue: GitHub.