{"record":{"id":"989b18ba357e978c","repo":"santifer/career-ops","slug":"too-many-redirects-max-redirects-for-url","errorCode":null,"errorMessage":"too many redirects (>${MAX_REDIRECTS}) for ${url}","messagePattern":"too many redirects \\(>(.+?)\\) for (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/_engine.mjs","lineNumber":436,"sourceCode":"        await resolveAndValidate(next.hostname, { allowsLocalhost });\n        if (next.hostname !== current.hostname) {\n          // Don't forward credentials across a hostname change (what the\n          // platform fetch does for cross-origin redirects; we do it manually).\n          reqHeaders = Object.fromEntries(Object.entries(reqHeaders).filter(([k]) => !/^(authorization|cookie)$/i.test(k)));\n        }\n        current = next;\n        continue;\n      }\n      if (!res.ok) {\n        const snippet = (await res.text().catch(() => '')).replace(/\\s+/g, ' ').trim().slice(0, 300);\n        const err = new Error(snippet ? `HTTP ${res.status}: ${snippet}` : `HTTP ${res.status}`);\n        // @ts-ignore\n        err.status = res.status;\n        throw err;\n      }\n      return res;\n    }\n    throw new Error(`too many redirects (>${MAX_REDIRECTS}) for ${url}`);\n  };\n}\n\n/**\n * Build the least-privilege ctx for a plugin. The scoped frozen env is a\n * CONVENIENCE (process.env is still globally reachable from any module) — the\n * real boundary is code review + trust.\n * @param {PluginManifestNormalized} manifest\n * @param {{ dryRun?: boolean, settings?: object }} [opts]\n * @returns {PluginContext}\n */\nexport function buildCtx(manifest, opts = {}) {\n  const scoped = {};\n  for (const name of [...manifest.requiredEnv, ...manifest.optionalEnv]) {\n    if (process.env[name] !== undefined) scoped[name] = process.env[name];\n  }\n  const env = Object.freeze({ ...scoped });\n  // Secret values long enough to be worth redacting (avoid no-op/over-redaction","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/plugins/_engine.mjs#L418-L454","documentation":"The guarded fetch wrapper follows up to MAX_REDIRECTS redirects, re-validating each hop against the egress policy (hostOk/SSRF checks). If it exceeds that limit, it gives up and throws this error naming the original URL — protecting against redirect loops and redirect-based sandbox escapes.","triggerScenarios":"A plugin fetch whose target responds with a redirect chain longer than MAX_REDIRECTS, including redirect loops (A → B → A) or misconfigured servers bounce-looping between www/apex or http/https.","commonSituations":"A stale short-link or tracking URL in a redirect loop; a server with broken TLS redirecting http→https→http; a login page bouncing unauthenticated requests between endpoints.","solutions":["Fetch the final URL directly instead of following the redirect chain","Fix the server's redirect loop (check http→https and www→apex rules)","Increase MAX_REDIRECTS only if the chain is legitimately long — prefer not to, since it loosens the sandbox guard","Test the URL with curl -IL to see the redirect chain and where it loops"],"exampleFix":"// before\nawait ctx.fetch('http://bit.ly/old-link'); // loops past MAX_REDIRECTS\n// Error: too many redirects (>3) for http://bit.ly/old-link\n// after: resolve the chain once, use the final destination\nawait ctx.fetch('https://example.com/final/destination');","handlingStrategy":"retry","validationCode":"// Pre-flight: resolve the redirect chain outside the sandbox limit\n// curl -sIL -o /dev/null -w '%{url_effective}' <url>  → use the effective URL\nconst finalUrl = await resolveRedirectsOnce(url); // via fetch with redirect:'manual', bounded\nawait ctx.fetch(finalUrl);","typeGuard":"null","tryCatchPattern":"try { return await ctx.fetch(url); } catch (e) { if (String(e.message).startsWith('too many redirects')) { /* resolve the final URL once, then retry against it */ } throw e; }","preventionTips":["Store final destination URLs, not short-links, in plugin configs","Fix http↔https and www/apex redirect loops on servers you control","Avoid raising MAX_REDIRECTS — a long chain usually indicates a server bug"],"tags":["plugins","network","http","redirects"],"backgroundTag":"too-many-redirects","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}