JuliusBrussee/caveman · error · TypeError

fetch failed: too many redirects

Error message

fetch failed: too many redirects

What it means

The proxy-aware fetch follows 3xx redirects automatically (for statuses 301/302/303/307/308 with a Location header) but caps the chain at MAX_REDIRECTS. When the server keeps redirecting past that limit, this TypeError aborts the request.

Source

Thrown at packages/cli/src/proxy-fetch.ts:352

      headers,
      body: buffered,
      signal: request.signal ?? null,
    };
    let hop = resolveProxyUrl(current.url, env);

    for (let redirects = 0; ; redirects += 1) {
      const response = hop ? await sendThroughProxy(current, hop) : await baseFetch(current.url, {
        method: current.method,
        headers: current.headers as HeadersInit,
        body: asBodyInit(current.body),
        signal: current.signal,
        redirect: "manual",
      });

      const location = response.headers.get("location");
      const redirectable = [301, 302, 303, 307, 308].includes(response.status);
      if (!redirectable || !location || request.redirect === "manual") return response;
      if (redirects >= MAX_REDIRECTS) throw new TypeError("fetch failed: too many redirects");
      if (request.redirect === "error") throw new TypeError("fetch failed: unexpected redirect");

      const next = new URL(location, current.url);
      const method = nextMethod(response.status, current.method);
      const bodyDropped = method !== current.method;
      void response.body?.cancel();
      current = {
        method,
        url: next,
        headers: redirectedHeaders(current.headers, current.url, next, bodyDropped),
        body: bodyDropped ? null : current.body,
        signal: current.signal,
      };
      hop = resolveProxyUrl(next, env);
    }
  } as typeof fetch;
}

View on GitHub (pinned to 5184b3d11a)

Solutions

  1. Fix the server-side redirect loop (check the Location targets and rewrite rules).
  2. Hit the final target URL directly to confirm the chain length: `curl -IL <url>`.
  3. Ensure cookies/auth headers needed by the redirect target are sent (redirects often drop credentials cross-origin).
  4. Check whether the proxy rewrites or re-redirects responses; bypass the proxy for that host (NO_PROXY).
  5. If the app must follow longer chains, raise MAX_REDIRECTS in proxy-fetch.ts or pass redirect: "manual" and handle hops yourself.

Example fix

// before
await fetch("http://old.example.com/loop"); // redirects forever
// after
const res = await fetch("https://new.example.com/final-target"); // call the canonical URL directly
Defensive patterns

Strategy: try-catch

Type guard

function isTooManyRedirects(e: unknown): boolean { return e instanceof TypeError && e.message.includes("too many redirects"); }

Try / catch

try {
  const res = await fetch(url);
} catch (e) {
  if (e instanceof TypeError && e.message.includes("too many redirects")) {
    console.error(`Redirect loop at ${url}; try the canonical URL or bypass the proxy`);
  } else throw e;
}

Prevention

When it happens

Trigger: A fetch through createProxyAwareFetch receives more than MAX_REDIRECTS consecutive redirect responses — typically a redirect loop (A -> B -> A) or an extremely long redirect chain.

Common situations: Misconfigured server rewriting http->http or cookie-dependent redirects (redirect requires a session cookie the client isn't sending through the proxy); auth-gated URLs bouncing between login endpoints; proxy intercepting and re-redirecting each hop.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@5184b3d11a (2026-08-31). Data as JSON: /api/errors/f7e11176f50ebf7f. Report an issue: GitHub.