{"record":{"id":"e0c90b56c07388e2","repo":"GopeedLab/gopeed","slug":"too-many-redirects-e0c90b","errorCode":null,"errorMessage":"too many redirects","messagePattern":"too many redirects","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/download/engine/inject/stream/module.go","lineNumber":751,"sourceCode":"\treqBuilder.DisableAutoReadResponse()\n\tfor _, header := range reqMeta.Headers {\n\t\treqBuilder.SetHeader(header[0], header[1])\n\t}\n\tif body != nil && reqMeta.Method != http.MethodGet && reqMeta.Method != http.MethodHead {\n\t\treqBuilder.SetBody(body)\n\t\tif contentType != \"\" && !hasHeader(reqMeta.Headers, \"Content-Type\") {\n\t\t\treqBuilder.SetHeader(\"Content-Type\", contentType)\n\t\t}\n\t}\n\tclient.SetRedirectPolicy(func(req *http.Request, via []*http.Request) error {\n\t\tswitch reqMeta.Redirect {\n\t\tcase \"manual\":\n\t\t\treturn http.ErrUseLastResponse\n\t\tcase \"error\":\n\t\t\treturn fmt.Errorf(\"redirect failed\")\n\t\tdefault:\n\t\t\tif len(via) > 20 {\n\t\t\t\treturn fmt.Errorf(\"too many redirects\")\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t})\n\tresp, err := reqBuilder.Send(reqMeta.Method, reqMeta.URL)\n\tif err != nil {\n\t\tvar ne net.Error\n\t\tif errorsAsTimeout(err, &ne) {\n\t\t\treturn nil, fmt.Errorf(\"Network request timed out\")\n\t\t}\n\t\treturn nil, fmt.Errorf(\"Network request failed: %w\", err)\n\t}\n\tid := fmt.Sprintf(\"%d\", time.Now().UnixNano())\n\tmeta := &fetchOpenMeta{\n\t\tID:         id,\n\t\tStatus:     resp.StatusCode,\n\t\tStatusText: resp.Status,\n\t\tURL:        reqMeta.URL,","sourceCodeStart":733,"sourceCodeEnd":769,"githubUrl":"https://github.com/GopeedLab/gopeed/blob/7b7327ffb30816273a74b142cccc0bc10c5a4c67/pkg/download/engine/inject/stream/module.go#L733-L769","documentation":"With the default redirect policy ('follow'), the injected fetch client aborts once a request chain exceeds 20 redirects (len(via) > 20). This mirrors browsers' safety cap and exists to stop redirect loops. The error propagates as a failed request wrapped in 'Network request failed: ...'.","triggerScenarios":"A URL that bounces between two or more hosts indefinitely (A→B→A...) under default follow mode; cookies not being kept across hops so a auth endpoint keeps redirecting to login; http→https→http server misconfiguration.","commonSituations":"Signed/expiring redirect tokens that regenerate forever for cookie-less clients; CDN edge loops when the User-Agent is blocked; extensions hitting a mirror list where each mirror redirects to the next in a ring.","solutions":["Enable cookie persistence for the request/session so auth redirects settle after login","Use redirect:'manual' and follow Location yourself, stopping when the URL repeats","Fix the server-side redirect loop or point the extension at the final canonical URL"],"exampleFix":"// before\nconst resp = await fetch(url); // 20+ hop loop -> too many redirects\n// after\nlet target = url;\nfor (let i = 0; i < 20; i++) {\n  const r = await fetch(target, { redirect: 'manual' });\n  if (r.status >= 300 && r.status < 400 && r.headers['location']) {\n    target = new URL(r.headers['location'], target).href;\n    continue;\n  }\n  break; // final response\n}","handlingStrategy":"validation","validationCode":"// JS: detect a redirect loop before fetching\nasync function resolvesWithin(url, maxHops = 20) {\n  const seen = new Set();\n  let target = url;\n  for (let i = 0; i < maxHops; i++) {\n    if (seen.has(target)) return false; // loop detected\n    seen.add(target);\n    const r = await fetch(target, { redirect: 'manual' });\n    const loc = r.headers && r.headers['location'];\n    if (!(r.status >= 300 && r.status < 400) || !loc) return true;\n    target = new URL(loc, target).href;\n  }\n  return false;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const resp = await fetch(url);\n} catch (e) {\n  if (String(e).includes('too many redirects')) {\n    // stop retrying: deterministic loop; fix cookies/URL/server instead\n  }\n}","preventionTips":["Enable cookies for the session so auth redirects terminate","Never retry a 'too many redirects' failure with identical request state","Track visited URLs when following redirects manually"],"tags":["network","fetch","redirect","http","loop"],"backgroundTag":null,"analyzedSha":"7b7327ffb30816273a74b142cccc0bc10c5a4c67","analyzedAt":"2026-08-16T02:51:03.250Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}