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

  1. 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.
  2. Verify the failing call's `completionClaim.contractRevision` (visible in the `item.started` event arguments) against the envelope's revision and correct the agent prompt.
  3. If a mid-run envelope update bumped the revision, abort and restart the turn so the agent works against one contract revision only.
  4. 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

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


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/8cd0d4fd33b45547. Report an issue: GitHub.