JuliusBrussee/caveman · error · Error
cave_harness_agent_mismatch
cave_harness_agent_mismatch
Error message
cave_harness_agent_mismatch
What it means
Thrown while preparing a locked harness (packages/agent/src/execution-kernel.ts:79): an agentId was supplied for the execution but it differs from the build.agent_id recorded in the CaveBuildLock. A lock is bound to one specific agent definition; running it against another agent's id is rejected.
Source
Thrown at packages/agent/src/execution-kernel.ts:79
}
export function prepareLockedHarnessExecution(input: {
build: CaveBuildLock;
harness: string;
adapterVersion: string;
upstreamVersion: string;
agentId?: string;
contextIR: ContextIR;
plan: CavePlan;
}): LockedHarnessPreparation {
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,View on GitHub (pinned to 27d5a3981a)
Solutions
- Regenerate the lock for the agent you are actually running (each agent gets its own lock).
- Verify the agent id string passed at run time matches the id in agent({...}) used at build time (ids are lowercase, max 96 chars).
- If the agent was renamed, rebuild all locks that referenced the old id.
Example fix
// before
const lock = loadLock("cave-build.json"); // built for agent "researcher"
prepareLockedHarness({ build: lock, agentId: "writer", /* ... */ });
// after
const lockForWriter = buildFor(agentDefinition("writer"));
prepareLockedHarness({ build: lockForWriter, agentId: "writer", /* ... */ }); Defensive patterns
Strategy: validation
Validate before calling
const lock = parseCaveBuildLock(rawLock);
if (input.agentId !== undefined && lock.agent_id !== input.agentId) {
throw new Error(`lock belongs to agent '${lock.agent_id}', got '${input.agentId}'`);
} Try / catch
try { prepareLockedHarness(input); }
catch (e) {
if (e instanceof Error && e.message === "cave_harness_agent_mismatch") {
// fetch/build the lock for THIS agent id, then retry once
input = { ...input, build: await lockForAgent(input.agentId!) };
prepareLockedHarness(input);
} else throw e;
} Prevention
- Derive lock paths from the agent id (one lock per agent) instead of a shared filename.
- Rebuild locks after renaming any agent id.
- Store the agent id in CI job configuration and assert it matches lock.agent_id before running.
When it happens
Trigger: Passing RunOptions/execution input with agentId set to a different agent than the one the lock was compiled from — e.g., reusing one agent's lock file for a sibling agent in the same project, or renaming an agent id after the lock was built.
Common situations: Multiple agents in one project sharing a lock path; renaming an agent's id in code without rebuilding; copy-pasting run code between agents while keeping the same lock reference.
Related errors
- option not found
- cave_harness_adapter_version_invalid
- cave_harness_model_invalid
- cave_harness_model_identity_missing
- cave_harness_wire_contract_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/b455c880ee18c7e2.
Report an issue: GitHub.