paperclipai/paperclip · error
Semantic result disposition does not match the terminal tool
Error message
Semantic result disposition does not match the terminal tool
What it means
The block tool (`prp_block`) must carry `reportedWorkDisposition === "blocked"` and the completion tool (`prp_completion`) must not. If the agent's structured result disposition contradicts which terminal tool it called, the driver rejects it. This keeps the machine-readable result consistent with the terminal action the agent took.
Source
Thrown at packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts:898
item: {
type: "tool_call",
id: call.callId,
name: tool,
arguments: call.arguments,
},
},
{ 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;View on GitHub (pinned to 01ad858492)
Solutions
- Retry the turn with explicit instruction: blocked work must use `prp_block` with `reportedWorkDisposition: "blocked"`; finished work must use `prp_completion` with a non-blocked disposition.
- Check the agent's system instructions/task envelope to confirm the two terminal tools and their dispositions are documented unambiguously.
- Inspect the failing call's arguments in the `item.started` event to confirm which mismatch occurred, then correct the agent's decision procedure.
- If the agent genuinely finished despite claiming blocked (or vice versa), clarify the work state and have it re-emit the correct terminal tool call.
Example fix
// before
prp_completion({ reportedWorkDisposition: "blocked", ... }) // mismatch
// after
prp_block({ reportedWorkDisposition: "blocked", summary: "waiting on API credentials", ... }) Defensive patterns
Strategy: validation
Validate before calling
const ok = (tool === 'prp_block') === (result.reportedWorkDisposition === 'blocked');
if (!ok) throw new Error('disposition/tool mismatch'); Type guard
function dispositionMatchesTool(tool, result) {
return tool === 'prp_block' ? result.reportedWorkDisposition === 'blocked'
: result.reportedWorkDisposition !== 'blocked';
} Try / catch
try {
await session.dispatchTool({ tool, callId, arguments });
} catch (e) {
if (e.message.includes('disposition does not match the terminal tool')) {
// instruct the agent to re-emit with the matching tool
} else throw e;
} Prevention
- Document prp_block vs prp_completion dispositions explicitly in agent prompts.
- Give the agent a decision rule: blocked => prp_block, otherwise prp_completion.
- Review failing calls' arguments to correct model behavior.
- Add prompt examples for both terminal tools.
When it happens
Trigger: Agent calls `prp_completion` with `reportedWorkDisposition: "blocked"`, or calls `prp_block` with a disposition other than `"blocked"` (e.g. `"completed"`), after passing basic schema validation.
Common situations: The agent blocked on a missing dependency but picked the completion tool by mistake; prompt instructions describing the two tools are ambiguous or contradictory; a model copies a template from the other tool.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid semantic result
- Semantic result completion contract revision does not match
- 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/8b9c97b6c431a56e.
Report an issue: GitHub.