koala73/worldmonitor · error · RssProxyPolicyError

Too many redirects

Error message

Too many redirects

What it means

Thrown by the direct-fetch redirect loop in the RSS proxy when the redirect chain exceeds MAX_DIRECT_REDIRECTS (3). The proxy manually follows redirects (to apply protocol and domain checks on each hop) and after 3 redirects it stops and throws RssProxyPolicyError with HTTP status 502. This prevents infinite redirect loops and bounds latency.

Source

Thrown at api/rss-proxy.js:169

      let currentUrl = parsedUrl;

      for (let redirectCount = 0; redirectCount <= MAX_DIRECT_REDIRECTS; redirectCount += 1) {
        const response = await fetchWithTimeout(currentUrl.href, {
          headers: DIRECT_FETCH_HEADERS,
          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 ffec79ac33)

Solutions

  1. Find the final canonical feed URL (follow the redirects manually in a browser or with curl -L) and use that URL directly to avoid the chain.
  2. If the domain consistently requires many redirects, add it to RELAY_ONLY_DOMAINS so the proxy uses the Railway relay (which handles redirects differently) instead of the bounded direct path.
  3. If the feed has a redirect loop (same URLs cycling), report it to the feed provider — this is a server misconfiguration.
  4. Increase MAX_DIRECT_REDIRECTS only if you understand the latency and loop-risk tradeoffs (not recommended for an edge function).

Example fix

// before — long redirect chain triggers the limit
GET /api/rss-proxy?url=http://old.feeds.example.com/news.xml
// after — use the final canonical URL directly
GET /api/rss-proxy?url=https://cdn.feeds.example.com/news.xml
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-resolve the feed URL to find its final canonical form
async function resolveCanonicalFeedUrl(feedUrl) {
  let url = feedUrl;
  for (let i = 0; i < 5; i++) { // one more than MAX_DIRECT_REDIRECTS to detect the issue
    const res = await fetch(url, { method: 'HEAD', redirect: 'manual' });
    const location = res.headers.get('location');
    if (!location || ![301,302,303,307,308].includes(res.status)) return url;
    url = new URL(location, url).href;
  }
  throw new Error(`Feed URL exceeds redirect limit; canonical URL: ${url}`);
}

Type guard

function isTooManyRedirectsError(e: unknown): e is { status: number } & Error {
  return e instanceof Error && (e as any).name === 'RssProxyPolicyError' && e.message === 'Too many redirects';
}

Try / catch

try {
  const feed = await fetch('/api/rss-proxy?url=' + encodeURIComponent(feedUrl));
} catch (e) {
  if (isTooManyRedirectsError(e)) {
    // Resolve the canonical URL and use it directly
    const canonical = await resolveCanonicalFeedUrl(feedUrl);
    const feed = await fetch('/api/rss-proxy?url=' + encodeURIComponent(canonical));
  } else throw e;
}

Prevention

When it happens

Trigger: An RSS feed URL that redirects more than 3 times before reaching a non-redirect (200/4xx/5xx) response — e.g. a feed that bounces between http and https, between apex and www, through a CDN chain, or a misconfigured redirect loop (A->B->A). Only 301/302/303/307/308 statuses count as redirects (DIRECT_REDIRECT_STATUSES).

Common situations: A feed behind multiple CDN layers (origin -> CDN -> www); a feed with an http-to-https redirect combined with an apex-to-www redirect (2 hops) plus one more; a genuine redirect loop from a misconfigured server; a feed that moved and chains through several old URLs.

Related errors


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