n8n-io/n8n · error · AxiosError

Request failed with status code ${response.status}

Error message

Request failed with status code ${response.status}

What it means

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.

Source

Thrown at packages/@n8n/backend-network/src/http/axios/redirect.ts:192

			headerPatternsToDropOnRedirect(downgradeToGet, stripCredentials),
		),
		...buildRedirectHopAgents(nextUrl, policy),
	};
}

/**
 * Enforces the caller's status policy on a terminal response, throwing the same `AxiosError` axios would.
 */
function throwIfStatusRejected(
	response: AxiosResponse,
	validateStatus: (status: number) => boolean,
): void {
	if (!validateStatus(response.status)) {
		// Same code axios derives in `settle`: 4xx -> ERR_BAD_REQUEST, 5xx -> ERR_BAD_RESPONSE, else undefined.
		const code = [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][
			Math.floor(response.status / 100) - 4
		];
		throw new AxiosError(
			`Request failed with status code ${response.status}`,
			code,
			response.config,
			response.request,
			response,
		);
	}
}

/**
 * Resolves a redirect `Location` against the current URL.
 * @throws OperationalError when the server returns a malformed Location that cannot be resolved.
 */
function resolveRedirectUrl(location: string, currentUrl: string): string {
	try {
		return new URL(location, currentUrl).href;
	} catch {
		throw new OperationalError(`Invalid redirect location received from server: ${location}`);

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Read the embedded response.status to classify (4xx client error vs 5xx server error).
  2. If the caller supplied a custom validateStatus, relax it to accept the returned status.
  3. For 5xx, retry with backoff; for 4xx, fix the request URL/params/auth.
  4. Inspect error.response.body for the upstream service's own error detail.

Example fix

// before - default validateStatus rejects 3xx-not-redirect and anything >= 300
const res = await followSsrfRedirects(config, policy);

// after - accept 4xx as a normal response and handle inline
const res = await followSsrfRedirects(
  { ...config, validateStatus: (s) => s >= 200 && s < 500 },
  policy,
);
if (res.status >= 400) { /* handle upstream error body */ }
Defensive patterns

Strategy: try-catch

Validate before calling

// Decide which statuses your caller can handle, then pass validateStatus
const validateStatus = (s: number) => s >= 200 && s < 400; // accept redirects handled by the layer

Type guard

import { isAxiosError } from 'axios';
const isStatusRejected = (e: unknown): boolean =>
  isAxiosError(e) && (e.code === 'ERR_BAD_REQUEST' || e.code === 'ERR_BAD_RESPONSE');

Try / catch

try {
  const res = await followSsrfRedirects(config, policy);
} catch (e) {
  if (isAxiosError(e) && typeof e.response?.status === 'number') {
    if (e.response.status >= 500) { /* retry with backoff */ }
    else if (e.response.status >= 400) { /* client error — fix request */ }
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/c1c8cc95fe6c5a73. Report an issue: GitHub.