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

  1. Rebuild the lock after any change to instructions, contexts, tools, or other static definition segments.
  2. Confirm the file sources feeding the Context IR are unchanged since the build (FileSource contents are part of static segments).
  3. 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

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


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/f0dc4542e81fbf53. Report an issue: GitHub.