{"record":{"id":"8d42380eefd453c5","repo":"paperclipai/paperclip","slug":"reasoncode","errorCode":"reasonCode","errorMessage":"message","messagePattern":"message","errorType":"http","errorClass":"ToolGatewayHttpError","httpStatus":422,"severity":"error","filePath":"server/src/services/tool-gateway.ts","lineNumber":10507,"sourceCode":"            : \"tool_gateway.call_failed\",\n          details: {\n            invocationId,\n            decision: isDeferred ? \"defer_runtime\" : \"deny\",\n            reasonCode,\n            tool: tool.name,\n            virtualToolName,\n            targetToolName: virtualToolName ? tool.name : undefined,\n            ...toolAuditMetadata(tool),\n            argumentsSummary: effectiveArgumentsSummary,\n            durationMs: Date.now() - startedAt,\n            error: message,\n            ...(executionAuditFromError(normalizedError)\n              ? { execution: executionAuditFromError(normalizedError) }\n              : {}),\n          },\n        });\n        if (normalizedError instanceof ToolContentValidationError) {\n          throw new ToolGatewayHttpError(422, message, reasonCode, {\n            findings: normalizedError.findings,\n          });\n        }\n        throw normalizedError;\n      }\n    },\n\n    async executePluginTool(input: ExecutePluginToolInput) {\n      if (!pluginToolDispatcher) {\n        throw new ToolGatewayHttpError(\n          501,\n          \"Plugin tool dispatch is not enabled\",\n          \"plugin_tools_disabled\",\n        );\n      }\n      if (input.actor.type === \"agent\") {\n        if (input.actor.companyId !== input.runContext.companyId) {\n          throw new ToolGatewayHttpError(","sourceCodeStart":10489,"sourceCodeEnd":10525,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/tool-gateway.ts#L10489-L10525","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncallTool({ name: \"search\", parameters }) // -> 422 reasonCode, findings\n// after\nconst res = callTool({ name: \"search\", parameters });\nif (res.status === 422) {\n  console.error(res.details.findings); // fix tool output per findings before retrying\n}","handlingStrategy":"try-catch","validationCode":"const findings = validateToolContentPreview(toolName, expectedOutput); if (findings.length) console.warn(\"tool output will fail validation\", findings);","typeGuard":"function isContentValidationError(e: unknown): e is ToolGatewayHttpError & { details: { findings: unknown[] } } {\n  return e instanceof ToolGatewayHttpError && e.status === 422 && Array.isArray((e.details as any)?.findings);\n}","tryCatchPattern":"try {\n  const out = await executeGatewayTool(input);\n} catch (e) {\n  if (isContentValidationError(e)) {\n    for (const f of e.details.findings) console.error(\"content invalid:\", f);\n    return { ok: false, findings: e.details.findings };\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["http","validation","tool-gateway"],"backgroundTag":"schema-validation-failed","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}