{"record":{"id":"f764b3e2a7db3af6","repo":"paperclipai/paperclip","slug":"error-reasoncode","errorCode":"error.reasonCode","errorMessage":"error.message","messagePattern":"error\\.message","errorType":"http","errorClass":"ToolGatewayHttpError","httpStatus":null,"severity":"error","filePath":"server/src/services/tool-gateway.ts","lineNumber":6124,"sourceCode":"          : null;\n      const result = normalizeMcpToolResult(\n        payloadRecord.result,\n        \"mcp_http\",\n        false,\n        sourceTemplateKey,\n      );\n      await markRemoteConnectionHealth(\n        connection,\n        \"ok\",\n        \"Remote MCP server responded to tools/call.\",\n      );\n      return { result, headerSummary, execution };\n    } catch (error) {\n      if (error instanceof RailwayError) {\n        throw new ToolGatewayHttpError(error.status, error.message, error.code, { connectionId: connection.id, catalogEntryId: entry.id, execution });\n      }\n      if (error instanceof ToolGatewayHttpError) {\n        throw new ToolGatewayHttpError(\n          error.status,\n          error.message,\n          error.reasonCode,\n          {\n            ...error.details,\n            execution: error.details.execution ?? execution,\n          },\n        );\n      }\n      if (error instanceof Error && error.name === \"AbortError\") {\n        await markRemoteConnectionHealth(\n          connection,\n          \"error\",\n          \"Remote MCP tool call timed out.\",\n        );\n        throw new ToolGatewayHttpError(\n          504,\n          \"Remote MCP tool call timed out\",","sourceCodeStart":6106,"sourceCodeEnd":6142,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/tool-gateway.ts#L6106-L6142","documentation":"This is the generic rethrow branch for ToolGatewayHttpError inside the remote tools/call handler: the existing error is rewrapped preserving status, message, and reasonCode while enriching details with the current execution record (error.details.execution ?? execution) and the connection/catalog context. Like error 493, message and code are dynamic and mirror the original thrown ToolGatewayHttpError.","triggerScenarios":"Any ToolGatewayHttpError thrown deeper in the remote MCP tools/call flow — e.g. mcp_*_not_found, railway_api_not_verified, vercel_connect_unavailable, request timeouts, auth failures — reaches this catch block and is rethrown with execution metadata attached.","commonSituations":"Debugging a failed tool execution and inspecting the enriched details (connectionId, catalogEntryId, execution trace); duplicate wrapping is prevented by reusing the original execution when already present.","solutions":["Inspect error.reasonCode and error.details (connectionId, catalogEntryId, execution) to find the root cause instead of the generic message.","Fix the underlying issue indicated by the reason code (config, credentials, handle, or endpoint).","Use the attached execution record to see request endpoint/protocol and how far the call progressed.","Retry only for transient reason codes (timeouts, 5xx); configuration/auth codes require corrective action first."],"exampleFix":"// before\ncatch (e) { console.log(e.message); } // 'error.message' tells little\n// after\ncatch (e) {\n  console.error(e.reasonCode, e.details.connectionId, e.details.execution);\n  if (e.reasonCode === \"railway_api_not_verified\") await reverifyRailway(e.details.connectionId);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"const isToolGatewayError = (e) => e instanceof ToolGatewayHttpError || (typeof e.reasonCode === \"string\" && typeof e.status === \"number\");","tryCatchPattern":"try {\n  return await gateway.invoke({ method: \"tools/call\", params });\n} catch (e) {\n  if (isToolGatewayError(e)) {\n    switch (e.reasonCode) {\n      case \"railway_api_not_verified\": return reverifyAndRetry(e);\n      case \"vercel_connect_unavailable\": return configureVercelConnectAndRetry(e);\n      case \"request_timeout\": return retryWithBackoff(e);\n      default: throw e;\n    }\n  }\n  throw e;\n}","preventionTips":["Branch handling on reasonCode and details, not the message string, since messages are dynamic.","Log e.details.execution to diagnose where remote calls fail.","Treat this rethrow as pass-through: fix the root reason code rather than retrying blindly.","Retry only transient reason codes; treat config/auth codes as actionable alerts."],"tags":["error-wrapping","rethrow","mcp"],"backgroundTag":"http-error-response","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}