{"record":{"id":"f40dccfec5cbd8c7","repo":"can1357/oh-my-pi","slug":"too-many-redirects-max-redirect-hops-fetchi","errorCode":null,"errorMessage":"Too many redirects (> ${MAX_REDIRECT_HOPS}) fetching ${url}","messagePattern":"Too many redirects \\(> (.+?)\\) fetching (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/mcp/transports/header-policy.ts","lineNumber":122,"sourceCode":"\t}\n\n\tconst configuredOrigin = new URL(url).origin;\n\tlet currentUrl = url;\n\tfor (let hop = 0; hop <= MAX_REDIRECT_HOPS; hop++) {\n\t\tconst attachConfigured = new URL(currentUrl).origin === configuredOrigin;\n\t\tconst headers = mergeMCPHeaders(attachConfigured ? sources : { generated: sources.generated });\n\t\tconst response = await fetch(currentUrl, { ...init, headers, redirect: \"manual\" });\n\t\tif (!REDIRECT_STATUSES[response.status]) return response;\n\n\t\tconst location = response.headers.get(\"Location\");\n\t\tif (!location) return response;\n\t\tawait response.body?.cancel();\n\t\tif (init.method !== \"GET\" && response.status !== 307 && response.status !== 308) {\n\t\t\tthrow new Error(`HTTP ${response.status}: server redirected a ${init.method} request; refusing to follow`);\n\t\t}\n\t\tcurrentUrl = new URL(location, currentUrl).href;\n\t}\n\tthrow new Error(`Too many redirects (> ${MAX_REDIRECT_HOPS}) fetching ${url}`);\n}\n","sourceCodeStart":104,"sourceCodeEnd":124,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/mcp/transports/header-policy.ts#L104-L124","documentation":"mcpFetch performs manual redirect handling for origin-locked MCP servers so configured headers (auth tokens) are not leaked on cross-origin hops. Each redirect hop re-evaluates the origin; after exceeding MAX_REDIRECT_HOPS (5) it gives up and throws this Error instead of looping forever.","triggerScenarios":"A request to an origin-locked MCP endpoint receives a chain of 301/302/303/307/308 responses with Location headers whose cumulative length exceeds 5 hops — typically a redirect loop or an excessively long redirect chain.","commonSituations":"Misconfigured MCP server URLs (e.g. pointing at a load balancer that bounces between http and https, or between hosts with trailing-slash mismatch); a server whose auth endpoint redirects to itself; proxies that keep redirecting to login pages.","solutions":["Verify the MCP URL is the final endpoint, not a redirector — fix the configured URL to point directly at the MCP server","Check the server's redirect chain with `curl -sIL <url>` and fix the loop (usually http→https or trailing-slash misconfiguration on the server)","If the redirect is intentional and ends at the same origin, disable origin locking so platform fetch handles redirects natively","Reduce intermediate proxies/load-balancer hops that each issue a redirect"],"exampleFix":"// before\nconst transport = new HttpTransport({ url: \"http://mcp.example.com/mcp\" }); // redirects to https://mcp.example.com/mcp/ ... chain exceeds 5 hops\n// after\nconst transport = new HttpTransport({ url: \"https://mcp.example.com/mcp/\" }); // final URL, no redirect chain","handlingStrategy":"validation","validationCode":"// Check the endpoint's redirect behavior before configuring it:\nconst res = await fetch(url, { redirect: \"manual\" });\nif ([301,302,303,307,308].includes(res.status)) console.warn(\"endpoint redirects; use the final URL\", res.headers.get(\"Location\"));","typeGuard":null,"tryCatchPattern":"try {\n  const res = await mcpFetch(url, init, sources, true);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"Too many redirects\")) {\n    // fall back to the platform fetch or surface a config error to the user\n  } else throw err;\n}","preventionTips":["Configure the final, post-redirect URL directly (https + correct path)","Check redirect chains with `curl -sIL` when onboarding a server","Avoid chaining proxies that each redirect","Watch for http→https and trailing-slash loops in server config"],"tags":["network","redirect","http","mcp"],"backgroundTag":"too-many-redirects","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}