{"record":{"id":"cb02a49e200b5303","repo":"paperclipai/paperclip","slug":"signed-arguments-mismatch","errorCode":"signed_arguments_mismatch","errorMessage":"Approved tool action arguments do not match reviewed hash","messagePattern":"Approved tool action arguments do not match reviewed hash","errorType":"http","errorClass":"ToolGatewayHttpError","httpStatus":409,"severity":"error","filePath":"server/src/services/tool-gateway.ts","lineNumber":5893,"sourceCode":"    // so it can never be approved. Do not replay it as a live approval. Expire\n    // the row and let the retry create a fresh, signable request. A null expiry\n    // alone (without this guard) also makes the getTime() check below unsafe.\n    const pendingRequest = match.actionRequest;\n    const pendingUnsigned =\n      pendingRequest.status === \"pending\"\n      && pendingRequest.signedArguments === null\n      && Date.now() - pendingRequest.createdAt.getTime() >= TOOL_ACTION_REQUEST_SIGNING_GRACE_MS;\n    const pendingExpired =\n      pendingRequest.status === \"pending\"\n      && pendingRequest.expiresAt !== null\n      && pendingRequest.expiresAt.getTime() <= Date.now();\n    if (pendingUnsigned || pendingExpired) {\n      const now = new Date();\n      await db.update(toolActionRequests).set({ status: \"expired\", resolvedAt: now, updatedAt: now }).where(and(\n        eq(toolActionRequests.id, match.actionRequest.id),\n        eq(toolActionRequests.status, \"pending\"),\n      ));\n      await db.update(toolInvocations).set({\n        approvalState: \"expired\",\n        idempotencyKey: null,\n        updatedAt: now,\n      }).where(eq(toolInvocations.id, match.invocation.id));\n      await reflectToolActionInteractionLifecycle({ actionRequestId: match.actionRequest.id, status: \"expired\" });\n      return null;\n    }\n    return match;\n  }\n\n  async function replayMatchingAgentAction(input: {\n    session: ToolGatewaySession;\n    toolName: string;\n    argumentsHash: string;\n  }) {\n    const match = await matchingAgentActionRequest(input);\n    if (!match) return null;\n    const { actionRequest, invocation } = match;","sourceCodeStart":5875,"sourceCodeEnd":5911,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/tool-gateway.ts#L5875-L5911","documentation":"Post-approval arguments integrity check: the canonical hash of the stored parameters does not match actionRequest.canonicalArgumentsHash, or the signature over the canonical arguments fails verification. The 409 blocks execution because the arguments drifted from what was actually reviewed and signed.","triggerScenarios":"Thrown at server/src/services/tool-gateway.ts:5706 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Arguments differ from the reviewed hash. Execute with exactly the approved arguments or request a new approval."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}