GopeedLab/gopeed · error
too many redirects
Error message
too many redirects
What it means
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: ...'.
Source
Thrown at pkg/download/engine/inject/stream/module.go:751
reqBuilder.DisableAutoReadResponse()
for _, header := range reqMeta.Headers {
reqBuilder.SetHeader(header[0], header[1])
}
if body != nil && reqMeta.Method != http.MethodGet && reqMeta.Method != http.MethodHead {
reqBuilder.SetBody(body)
if contentType != "" && !hasHeader(reqMeta.Headers, "Content-Type") {
reqBuilder.SetHeader("Content-Type", contentType)
}
}
client.SetRedirectPolicy(func(req *http.Request, via []*http.Request) error {
switch reqMeta.Redirect {
case "manual":
return http.ErrUseLastResponse
case "error":
return fmt.Errorf("redirect failed")
default:
if len(via) > 20 {
return fmt.Errorf("too many redirects")
}
return nil
}
})
resp, err := reqBuilder.Send(reqMeta.Method, reqMeta.URL)
if err != nil {
var ne net.Error
if errorsAsTimeout(err, &ne) {
return nil, fmt.Errorf("Network request timed out")
}
return nil, fmt.Errorf("Network request failed: %w", err)
}
id := fmt.Sprintf("%d", time.Now().UnixNano())
meta := &fetchOpenMeta{
ID: id,
Status: resp.StatusCode,
StatusText: resp.Status,
URL: reqMeta.URL,View on GitHub (pinned to 7b7327ffb3)
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
Example fix
// before
const resp = await fetch(url); // 20+ hop loop -> too many redirects
// after
let target = url;
for (let i = 0; i < 20; i++) {
const r = await fetch(target, { redirect: 'manual' });
if (r.status >= 300 && r.status < 400 && r.headers['location']) {
target = new URL(r.headers['location'], target).href;
continue;
}
break; // final response
} Defensive patterns
Strategy: validation
Validate before calling
// JS: detect a redirect loop before fetching
async function resolvesWithin(url, maxHops = 20) {
const seen = new Set();
let target = url;
for (let i = 0; i < maxHops; i++) {
if (seen.has(target)) return false; // loop detected
seen.add(target);
const r = await fetch(target, { redirect: 'manual' });
const loc = r.headers && r.headers['location'];
if (!(r.status >= 300 && r.status < 400) || !loc) return true;
target = new URL(loc, target).href;
}
return false;
} Try / catch
try {
const resp = await fetch(url);
} catch (e) {
if (String(e).includes('too many redirects')) {
// stop retrying: deterministic loop; fix cookies/URL/server instead
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of GopeedLab/gopeed@7b7327ffb3 (2026-08-16).
Data as JSON: /api/errors/e0c90b56c07388e2.
Report an issue: GitHub.