paperclipai/paperclip · error · ToolGatewayHttpError
reasonCode
reasonCode
Error message
message
What it means
The tool gateway wraps tool-content validation failures as ToolGatewayHttpError with HTTP status 422. When a tool's normalized output fails ToolContentValidationError, the gateway rethrows as a 422 carrying a reasonCode and the validator's findings array, after recording the execution audit entry. Callers (agents/board routes) receive a structured HTTP error describing exactly which content checks failed.
Solutions
- Read the 422 response's details.findings array — it lists each validation failure; fix the tool output to satisfy those checks.
- Inspect the matching execution audit entry (executionAuditFromError) for the exact tool, run, and slot that produced invalid content.
- Update the tool's declared output schema/validator in the connector definition if the new shape is legitimate.
- If the upstream tool was upgraded, pin or adapt the connector to its new output format and re-run the tool call.
Example fix
// before
callTool({ name: "search", parameters }) // -> 422 reasonCode, findings
// after
const res = callTool({ name: "search", parameters });
if (res.status === 422) {
console.error(res.details.findings); // fix tool output per findings before retrying
} Defensive patterns
Strategy: try-catch
Validate before calling
const findings = validateToolContentPreview(toolName, expectedOutput); if (findings.length) console.warn("tool output will fail validation", findings); Type guard
function isContentValidationError(e: unknown): e is ToolGatewayHttpError & { details: { findings: unknown[] } } {
return e instanceof ToolGatewayHttpError && e.status === 422 && Array.isArray((e.details as any)?.findings);
} Try / catch
try {
const out = await executeGatewayTool(input);
} catch (e) {
if (isContentValidationError(e)) {
for (const f of e.details.findings) console.error("content invalid:", f);
return { ok: false, findings: e.details.findings };
}
throw e;
} Prevention
- Keep tool output validators and the connector's declared schema in sync after every tool upgrade.
- Add a contract test that runs each tool fixture through the content validator.
- Log details.findings from every 422 to detect recurring tool output drift early.
When it happens
Trigger: A gateway tool call completes but its returned content fails schema/content validation, e.g. a tool returns malformed JSON output, missing required fields, or content exceeding declared limits, so ToolContentValidationError is raised during executeGatewayTool.
Common situations: An MCP/tool backend changed its response shape after an upgrade; a custom fixture tool emits output not matching the declared tool contract; a connector emits truncated or invalid content under timeout; a new tool registered without its output validator config.
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
- A full lowercase source SHA is required.
- A reusable lease cannot be replaced and reacquired in the…
- A reusable lease handoff requires an execution workspace…
- A safe, unique --revision is required
- A same-run reusable lease reacquisition requires a…
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/8d42380eefd453c5.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/tool-gateway.ts:10507
: "tool_gateway.call_failed",
details: {
invocationId,
decision: isDeferred ? "defer_runtime" : "deny",
reasonCode,
tool: tool.name,
virtualToolName,
targetToolName: virtualToolName ? tool.name : undefined,
...toolAuditMetadata(tool),
argumentsSummary: effectiveArgumentsSummary,
durationMs: Date.now() - startedAt,
error: message,
...(executionAuditFromError(normalizedError)
? { execution: executionAuditFromError(normalizedError) }
: {}),
},
});
if (normalizedError instanceof ToolContentValidationError) {
throw new ToolGatewayHttpError(422, message, reasonCode, {
findings: normalizedError.findings,
});
}
throw normalizedError;
}
},
async executePluginTool(input: ExecutePluginToolInput) {
if (!pluginToolDispatcher) {
throw new ToolGatewayHttpError(
501,
"Plugin tool dispatch is not enabled",
"plugin_tools_disabled",
);
}
if (input.actor.type === "agent") {
if (input.actor.companyId !== input.runContext.companyId) {
throw new ToolGatewayHttpError(View on GitHub (pinned to 3f1d897a7c)