paperclipai/paperclip · error · ToolGatewayHttpError
approved_tool_target_changed
approved_tool_target_changed
Error message
Tool definition or connection changed; request a new review
What it means
Post-approval integrity check: the signed payload decoded but the target it names (tool/invocation identity) differs from what the stored invocation now references, meaning the review target changed after the board reviewed it. Execution is refused with 409 so a modified action never runs under a stale approval.
Solutions
- The tool/target changed after review. Re-submit for approval with the final target; never alter an approved action's target.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at server/src/services/tool-gateway.ts:5675 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/cdf29000ab530468.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/tool-gateway.ts:9460
agentId: invocation.agentId,
runId: invocation.runId,
issueId: issue.id,
projectId: issue.projectId,
createdAt: new Date(),
expiresAt: new Date(Date.now() + DEFAULT_SESSION_TTL_MS),
};
await restoreApprovedActionIdentity(
session,
signedPayload.identityContextId,
);
const tool = await findToolForSession(session, invocation.toolName);
if (
!approvalSnapshotsMatch(
signedPayload.approvalSnapshot,
await connectedRemoteApprovalSnapshot(session, tool),
)
)
throw new ToolGatewayHttpError(
409,
"Tool definition or connection changed; request a new review",
"approved_tool_target_changed",
);
const access = await policyService.decide(
policyInputForTool({
session,
tool,
parameters: signedPayload.arguments,
}),
);
if (!access.allowed && access.decision !== "require_approval")
throw new ToolGatewayHttpError(
403,
access.explanation,
access.reasonCode,
);
}View on GitHub (pinned to 3f1d897a7c)