{"record":{"id":"37ce55508b5dfd5f","repo":"diegosouzapw/OmniRoute","slug":"subscription-fetch-too-many-redirects","errorCode":null,"errorMessage":"Subscription fetch: too many redirects","messagePattern":"Subscription fetch: too many redirects","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/proxySubscription/subscriptionService.ts","lineNumber":341,"sourceCode":" * handling, and re-validate any redirect target. Throws on non-2xx or a\n * blocked target. Each attempt owns its own timeout so a retry after a fast\n * failure isn't killed by the previous attempt's timer.\n */\nasync function doSafeFetch(url: string, headers: Record<string, string>): Promise<string> {\n  await assertSafeFetchTarget(url);\n  const controller = new AbortController();\n  const timeout = setTimeout(() => controller.abort(), SUBSCRIPTION_FETCH_TIMEOUT_MS);\n  try {\n    const res = await fetch(url, { redirect: \"manual\", signal: controller.signal, headers });\n    if (res.status >= 300 && res.status < 400) {\n      const loc = res.headers.get(\"location\");\n      if (!loc) throw new Error(\"Subscription fetch redirected without Location\");\n      // Resolve relative redirects and re-validate the target (SSRF guard).\n      const next = new URL(loc, url).toString();\n      await assertSafeFetchTarget(next);\n      const res2 = await fetch(next, { redirect: \"manual\", signal: controller.signal, headers });\n      if (res2.status >= 300 && res2.status < 400) {\n        throw new Error(\"Subscription fetch: too many redirects\");\n      }\n      if (!res2.ok) {\n        throw new Error(`Subscription fetch failed: HTTP ${res2.status}`);\n      }\n      return await res2.text();\n    }\n    if (!res.ok) {\n      throw new Error(`Subscription fetch failed: HTTP ${res.status}`);\n    }\n    return await res.text();\n  } finally {\n    clearTimeout(timeout);\n  }\n}\n\n/**\n * Classify a fetch error as retryable. Transient (retry): network/timeout/DNS\n * failures, HTTP 5xx, and HTTP 429. Permanent (no retry): 4xx client errors","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/diegosouzapw/OmniRoute/blob/a179ffed5bb2e0b883b9ae7214ce8717b2a94c4d/src/lib/proxySubscription/subscriptionService.ts#L323-L359","documentation":"Error \"Subscription fetch: too many redirects\" thrown in diegosouzapw/OmniRoute.","triggerScenarios":"Thrown at src/lib/proxySubscription/subscriptionService.ts:341 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"a179ffed5bb2e0b883b9ae7214ce8717b2a94c4d","analyzedAt":"2026-08-25T18:35:09.898Z","schemaVersion":2},"datasetVersion":"2026-08-25T21:54:21.419Z"}