{"record":{"id":"0bc35d9c4af13199","repo":"paperclipai/paperclip","slug":"method-path-failed-with-status","errorCode":null,"errorMessage":"${method} ${path} failed with ${status}","messagePattern":"(.+?) (.+?) failed with (.+?)","errorType":"http","errorClass":"PaperclipApiError","httpStatus":null,"severity":"error","filePath":"packages/mcp-server/src/client.ts","lineNumber":103,"sourceCode":"      Authorization: `Bearer ${this.config.apiKey}`,\n      Accept: \"application/json\",\n    };\n    if (options.body !== undefined) {\n      headers[\"Content-Type\"] = \"application/json\";\n    }\n    if ((options.includeRunId ?? isWriteMethod(method)) && this.config.runId) {\n      headers[\"X-Paperclip-Run-Id\"] = this.config.runId;\n    }\n\n    const response = await fetch(url, {\n      method,\n      headers,\n      body: options.body === undefined ? undefined : JSON.stringify(options.body),\n    });\n    const parsedBody = await parseResponseBody(response);\n\n    if (!response.ok) {\n      throw new PaperclipApiError({\n        status: response.status,\n        method: method.toUpperCase(),\n        path,\n        body: parsedBody,\n        message: buildErrorMessage(method.toUpperCase(), path, response.status, parsedBody),\n      });\n    }\n\n    return parsedBody as T;\n  }\n}\n","sourceCodeStart":85,"sourceCodeEnd":115,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/mcp-server/src/client.ts#L85-L115","documentation":"Same throw site as 450 (PaperclipApiError from requestJson on a non-OK response), but buildErrorMessage takes the shorter branch because the parsed body did not contain a string 'error' field — e.g. an empty body, plain text, or a JSON shape without 'error'. You still get status, method, and path on the error object, just no server message.","triggerScenarios":"Upstream returns non-2xx with an empty body (gateway/proxy 502/504), plain-text error from a reverse proxy, or a JSON envelope that uses a different key ('message', 'detail') than 'error'.","commonSituations":"A proxy in front of Paperclip returning HTML/text errors; the server crashed mid-request; a route that returns a non-standard error format.","solutions":["Inspect the raw response — curl the same path directly to see the actual body.","If a proxy is returning the error, fix the proxy/upstream config.","On the client, read PaperclipApiError.body (parsedBody) for any non-'error' field that may carry detail."],"exampleFix":"// status 502 with empty body -> 'GET /api/issues failed with 502'\n// diagnose directly\ncurl -i -H \"Authorization: Bearer $PAPERCLIP_API_KEY\" $URL/api/issues","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isPaperclipApiError(e: unknown): e is { status: number; method: string; path: string; body: unknown; message: string } {\n  return typeof e === 'object' && e !== null && 'status' in e && typeof (e as any).status === 'number';\n}","tryCatchPattern":"try { await client.requestJson(method, path, opts) }\ncatch (e) {\n  if (isPaperclipApiError(e) && e.body == null && e.status >= 500) { /* likely proxy/upstream — do not retry blindly */ }\n  throw e;\n}","preventionTips":["When the message lacks ': <reason>', curl the path directly to see the real body.","Suspect a reverse proxy or gateway when status is 502/503/504.","Log PaperclipApiError.body to capture non-'error' envelope shapes."],"tags":["api-client","paperclip-mcp","http-error","upstream","diagnostics"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}