n8n-io/n8n · error · OperationalError

Maximum number of redirects (${maxRedirects}) exceeded

Error message

Maximum number of redirects (${maxRedirects}) exceeded

What it means

OperationalError thrown by followSsrfRedirects when redirectCount reaches maxRedirects (default MAX_REDIRECTS_DEFAULT, overridable via initialConfig.maxRedirects). Each 3xx hop increments redirectCount; if the chain does not terminate within the budget, the loop aborts to prevent redirect cycles.

Source

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

	for (let redirectCount = 0; ; redirectCount++) {
		const response = await invokeAxios(config, policy.authSendImmediately);
		const location = getRedirectLocation(response);

		if (!isRedirectStatus(response.status) || !location) {
			if (isRedirectStatus(response.status)) {
				throwIfStatusRejected(response, baseValidateStatus);
			}
			return response;
		}

		// This response is a redirect we will not return.
		// Release its body (a no-op for buffered bodies, frees the socket for streamed ones)
		// before we either stop or follow.
		discardResponseBody(response);

		if (redirectCount >= maxRedirects) {
			throw new OperationalError(`Maximum number of redirects (${maxRedirects}) exceeded`);
		}

		const nextUrl = resolveRedirectUrl(location, currentUrl);
		throwIfDomainNotAllowed(nextUrl, policy.allowedDomains);
		await validateUrlSsrf(nextUrl, policy.ssrf);

		config = prepareHop(
			buildRedirectHopConfig(config, response.status, originalUrl, nextUrl, policy),
		);
		currentUrl = nextUrl;
	}
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Inspect the captured chain (log each currentUrl/Location) to find the loop point.
  2. Fix the server-side redirect rule that creates the cycle.
  3. If a long legitimate chain is expected, raise initialConfig.maxRedirects deliberately.
  4. Verify cookies/auth are being sent so the server stops bouncing to a login page.

Example fix

// before
const res = await followSsrfRedirects(config, policy);

// after - allow a longer legitimate chain
const res = await followSsrfRedirects(
  { ...config, maxRedirects: 21 },
  policy,
);
Defensive patterns

Strategy: try-catch

Validate before calling

// Cap the redirect budget deliberately per call
const maxRedirects = config.maxRedirects ?? 5;

Type guard

import { OperationalError } from 'n8n-workflow';
const isTooManyRedirects = (e: unknown): boolean =>
  e instanceof OperationalError && /Maximum number of redirects/.test(e.message);

Try / catch

try {
  const res = await followSsrfRedirects(config, policy);
} catch (e) {
  if (e instanceof OperationalError && /Maximum number of redirects/.test(e.message)) {
    // likely a redirect loop — log the chain and surface 'upstream misconfigured'
  }
  throw e;
}

Prevention

When it happens

Trigger: The target URL returns a chain of 3xx responses longer than maxRedirects. Common shapes: A->B->A ping-pong, a long sequential chain, or a final hop that itself keeps redirecting. The check fires before following the (maxRedirects+1)th hop.

Common situations: A misconfigured login/auth flow that keeps redirecting; a CDN edge loop; an erroneously configured trailing-slash rewrite rule alternating between two URLs; a server that redirects to itself with a session cookie it never accepts.

Related errors


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