koala73/worldmonitor · error · RssProxyPolicyError

Too many redirects

Error message

Too many redirects

What it means

fetchDirect follows at most MAX_DIRECT_REDIRECTS = 3 manual hops (301/302/303/307/308). When the fourth hop is still a redirect, the proxy gives up with this RssProxyPolicyError and HTTP 502. The bound exists to keep redirect loops from burning the Edge function invocation.

Solutions

  1. Count the hops: curl -sIL -o /dev/null -w '%{num_redirects}\n' '<feed-url>'
  2. Request the final destination URL directly through the proxy
  3. Fix the origin's redirect loop — alternating apex/www rewrite rules are the usual cause
  4. Only if chains are legitimately longer, raise MAX_DIRECT_REDIRECTS in api/rss-proxy.js and re-check the Edge timeout budget

Example fix

# before — chain longer than 3 hops
$ curl -sIL -o /dev/null -w '%{num_redirects}\n' 'https://old.example.com/rss'
5                                              # proxy answers 502 Too many redirects

# after — call the proxy with the resolved final URL
GET /api/rss-proxy?url=https://final.example.com/rss
Defensive patterns

Strategy: validation

Validate before calling

// Count hops before handing the URL to the proxy (limit is 3)
async function hopCount(url) {
  let n = 0, current = new URL(url);
  for (;;) {
    const res = await fetch(current, { redirect: 'manual' });
    const loc = res.headers.get('location');
    if (!loc || ![301,302,303,307,308].includes(res.status)) return { hops: n, finalUrl: current.href };
    n += 1; current = new URL(loc, current);
    if (n > 3) return { hops: n, finalUrl: current.href };
  }
}

Try / catch

try { await fetchFeedViaProxy(feedUrl); }
catch (err) {
  if (/Too many redirects/.test(err.message)) {
    const { finalUrl } = await hopCount(feedUrl);
    return fetchFeedViaProxy(finalUrl);   // retry once with the resolved destination
  }
  throw err;
}

Prevention

When it happens

Trigger: A↔B redirect loops on the origin (typically alternating apex/www rewrite rules); cookie/consent walls that redirect forever because the proxy sends no cookies; legitimate chains longer than three hops (http→https→apex→www→feed).

Common situations: Publisher consent-redirect walls; misconfigured origin rewrites; chains that quietly grew one hop when a new canonical domain was introduced.

Related errors


AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-08-21). Data as JSON: /api/errors/dcc91d8c0cf296a7. Report an issue: GitHub.

Appendix: source

Thrown at api/rss-proxy.js:321

      let currentUrl = parsedUrl;

      for (let redirectCount = 0; redirectCount <= MAX_DIRECT_REDIRECTS; redirectCount += 1) {
        const response = await fetchRssResponse(currentUrl.href, {
          headers: rssFetchHeadersForHost(currentUrl.hostname),
          redirect: 'manual',
        }, timeout);

        if (!DIRECT_REDIRECT_STATUSES.has(response.status)) {
          return response;
        }

        const location = response.headers.get('location');
        if (!location) {
          return response;
        }

        if (redirectCount === MAX_DIRECT_REDIRECTS) {
          throw new RssProxyPolicyError('Too many redirects', 502);
        }

        const redirectUrl = new URL(location, currentUrl.href);
        assertAllowedRedirect(redirectUrl);
        currentUrl = redirectUrl;
      }
    };

    let response;
    let usedRelay = false;

    if (isRelayOnly) {
      // Skip direct fetch entirely — these domains block Vercel IPs
      response = await fetchViaRailway(feedUrl, timeout);
      usedRelay = !!response;
      if (!response) throw new Error(`Railway relay unavailable for relay-only domain: ${hostname}`);
    } else {
      try {

View on GitHub (pinned to e586b8b4b8)