{"record":{"id":"c1c8cc95fe6c5a73","repo":"n8n-io/n8n","slug":"request-failed-with-status-code-response-status","errorCode":null,"errorMessage":"Request failed with status code ${response.status}","messagePattern":"Request failed with status code (.+?)","errorType":"http","errorClass":"AxiosError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/backend-network/src/http/axios/redirect.ts","lineNumber":192,"sourceCode":"\t\t\theaderPatternsToDropOnRedirect(downgradeToGet, stripCredentials),\n\t\t),\n\t\t...buildRedirectHopAgents(nextUrl, policy),\n\t};\n}\n\n/**\n * Enforces the caller's status policy on a terminal response, throwing the same `AxiosError` axios would.\n */\nfunction throwIfStatusRejected(\n\tresponse: AxiosResponse,\n\tvalidateStatus: (status: number) => boolean,\n): void {\n\tif (!validateStatus(response.status)) {\n\t\t// Same code axios derives in `settle`: 4xx -> ERR_BAD_REQUEST, 5xx -> ERR_BAD_RESPONSE, else undefined.\n\t\tconst code = [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][\n\t\t\tMath.floor(response.status / 100) - 4\n\t\t];\n\t\tthrow new AxiosError(\n\t\t\t`Request failed with status code ${response.status}`,\n\t\t\tcode,\n\t\t\tresponse.config,\n\t\t\tresponse.request,\n\t\t\tresponse,\n\t\t);\n\t}\n}\n\n/**\n * Resolves a redirect `Location` against the current URL.\n * @throws OperationalError when the server returns a malformed Location that cannot be resolved.\n */\nfunction resolveRedirectUrl(location: string, currentUrl: string): string {\n\ttry {\n\t\treturn new URL(location, currentUrl).href;\n\t} catch {\n\t\tthrow new OperationalError(`Invalid redirect location received from server: ${location}`);","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/backend-network/src/http/axios/redirect.ts#L174-L210","documentation":"AxiosError thrown by throwIfStatusRejected inside followSsrfRedirects when the terminal (non-redirect) response fails the caller's validateStatus policy. It mirrors the code axios itself derives in settle: 4xx -> ERR_BAD_REQUEST, 5xx -> ERR_BAD_RESPONSE. Because the redirect layer runs with maxRedirects:0 and a permissive validateStatus for 3xx, only the final response reaches this check.","triggerScenarios":"followSsrfRedirects receives a non-3xx response (or a 3xx without a Location) whose status is rejected by baseValidateStatus (default: status < 200 or >= 300). throwIfStatusRejected then re-throws an AxiosError carrying config, request, and response for compatibility with axios consumers.","commonSituations":"A node HTTP request returns 404/500 on the final hop; the caller passed a custom validateStatus that rejects the returned status; the target endpoint is down; SSRF-validated target returns an error after redirects.","solutions":["Read the embedded response.status to classify (4xx client error vs 5xx server error).","If the caller supplied a custom validateStatus, relax it to accept the returned status.","For 5xx, retry with backoff; for 4xx, fix the request URL/params/auth.","Inspect error.response.body for the upstream service's own error detail."],"exampleFix":"// before - default validateStatus rejects 3xx-not-redirect and anything >= 300\nconst res = await followSsrfRedirects(config, policy);\n\n// after - accept 4xx as a normal response and handle inline\nconst res = await followSsrfRedirects(\n  { ...config, validateStatus: (s) => s >= 200 && s < 500 },\n  policy,\n);\nif (res.status >= 400) { /* handle upstream error body */ }","handlingStrategy":"try-catch","validationCode":"// Decide which statuses your caller can handle, then pass validateStatus\nconst validateStatus = (s: number) => s >= 200 && s < 400; // accept redirects handled by the layer","typeGuard":"import { isAxiosError } from 'axios';\nconst isStatusRejected = (e: unknown): boolean =>\n  isAxiosError(e) && (e.code === 'ERR_BAD_REQUEST' || e.code === 'ERR_BAD_RESPONSE');","tryCatchPattern":"try {\n  const res = await followSsrfRedirects(config, policy);\n} catch (e) {\n  if (isAxiosError(e) && typeof e.response?.status === 'number') {\n    if (e.response.status >= 500) { /* retry with backoff */ }\n    else if (e.response.status >= 400) { /* client error — fix request */ }\n  }\n  throw e;\n}","preventionTips":["Pass a deliberate validateStatus so expected non-2xx do not throw.","Read error.response.status to classify before retrying.","Distinguish 4xx (do not retry) from 5xx (retry) at the call site."],"tags":["http","axios","redirect","ssrf","status-code","backend-network"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}