paperclipai/paperclip · error
Semantic result completion contract revision does not match
Error message
Semantic result completion contract revision does not match
What it means
The structured result's `completionClaim.contractRevision` must equal the revision in the driver's task envelope completion contract (`#taskEnvelope.completionContract.revision`). If the agent claims a result against a different contract revision, the driver rejects it so results cannot be accepted against a stale or future contract.
Source
Thrown at packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts:905
{ turnId, itemId: call.callId },
);
if (tool === PRP_COMPLETION_TOOL_NAME || tool === PRP_BLOCK_TOOL_NAME) {
const validation = validatePrpStructuredRunResult(call.arguments);
if (!validation.ok) throw new Error("Invalid semantic result");
if (
(tool === PRP_BLOCK_TOOL_NAME &&
validation.result.reportedWorkDisposition !== "blocked") ||
(tool === PRP_COMPLETION_TOOL_NAME &&
validation.result.reportedWorkDisposition === "blocked")
)
throw new Error(
"Semantic result disposition does not match the terminal tool",
);
if (
validation.result.completionClaim.contractRevision !==
this.#taskEnvelope.completionContract.revision
) {
throw new Error(
"Semantic result completion contract revision does not match",
);
}
const fingerprint = canonicalJson(validation.result);
if (this.#resultFingerprint && this.#resultFingerprint !== fingerprint)
throw new Error("A different semantic result was already committed");
if (!this.#resultFingerprint) {
this.#result = structuredClone(validation.result);
this.#resultFingerprint = fingerprint;
this.#resultCallId = call.callId;
this.#resultTurnId = turnId;
this.#semanticResultTextBoundary = this.#completedTextParts.length;
this.#emit("run.result.proposed", validation.result, {
turnId,
itemId: call.callId,
});
}
this.#emit(View on GitHub (pinned to 01ad858492)
Solutions
- Re-send the current task envelope (full-context turn) so the agent holds the latest completion contract revision, then let it re-emit the terminal call.
- Verify the failing call's `completionClaim.contractRevision` (visible in the `item.started` event arguments) against the envelope's revision and correct the agent prompt.
- If a mid-run envelope update bumped the revision, abort and restart the turn so the agent works against one contract revision only.
- Ensure the driver instance constructing the envelope is the same one the agent session was seeded from — mismatched instances carry different revisions.
Example fix
// before (agent arguments)
completionClaim: { contractRevision: 1, ... } // envelope revision is 2 -> mismatch
// after
// re-issue prompt with current envelope, agent then emits:
completionClaim: { contractRevision: 2, ... } Defensive patterns
Strategy: validation
Validate before calling
const snap = await session.snapshot(); if (claim.contractRevision !== envelope.completionContract.revision) throw new RevisionMismatchError();
Type guard
function revisionMatches(claim, envelope) { return claim.contractRevision === envelope.completionContract.revision; } Try / catch
try {
await session.dispatchTool({ tool, callId, arguments });
} catch (e) {
if (e.message.includes('contract revision does not match')) {
// restart the turn with the current task envelope
} else throw e;
} Prevention
- Always send the current task envelope (full-context) after any revision bump.
- Never hardcode revision numbers in agent instructions.
- Abort and restart turns when the envelope changes mid-run.
- Verify driver and agent session share the same envelope instance.
When it happens
Trigger: Agent emits a terminal tool call whose `completionClaim.contractRevision` differs from the envelope revision — e.g. the agent echoed a revision from an old prompt, the envelope was re-issued with a bumped revision mid-run, or a resumed session replays an old result after the contract was revised.
Common situations: Task envelope regenerated (revision bumped) between retries while the agent still holds cached instructions with the old revision; a resumed OpenCode session answers with a result minted before the envelope update; instruction template pinned to a fixed revision number.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Invalid semantic result
- Semantic result disposition does not match the terminal tool
- A different semantic result was already committed
- OpenCode evals require exact version 1.18.17; received ${ver
- [opencode-local] Remote model availability probe for "${mode
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/8cd0d4fd33b45547.
Report an issue: GitHub.