GopeedLab/gopeed · error
redirect failed
Error message
redirect failed
What it means
In the injected fetch implementation, reqMeta.Redirect maps to the fetch() 'redirect' option. When the extension sets redirect:"error", the client's redirect policy returns this error for ANY 3xx response, mirroring the browser fetch spec where redirect:'error' rejects on a redirect. The error surfaces as a failed fetch wrapped in 'Network request failed'.
Source
Thrown at pkg/download/engine/inject/stream/module.go:748
}()
reqBuilder := client.R()
reqBuilder.SetContext(ctx)
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,View on GitHub (pinned to 7b7327ffb3)
Solutions
- Use the default redirect:'follow' when you want the final response
- Use redirect:'manual' to inspect the 3xx and its Location header yourself
- Resolve the target URL first (follow once manually) and pass the final URL with redirect:'error'
Example fix
// before
const resp = await fetch(url, { redirect: 'error' }); // 302 -> redirect failed
// after
const resp = await fetch(url, { redirect: 'follow' }); // or 'manual' to read Location Defensive patterns
Strategy: validation
Validate before calling
// JS: choose redirect mode deliberately before fetching
const REDIRECT = new Set(['follow', 'manual', 'error']);
const mode = REDIRECT.has(opts.redirect) ? opts.redirect : 'follow';
if (mode === 'error') {
// preflight: a HEAD probe tells you if the URL redirects before you commit
const probe = await fetch(url, { method: 'HEAD', redirect: 'manual' });
if (probe.status >= 300 && probe.status < 400) throw new Error('URL redirects; use follow/manual');
}
const resp = await fetch(url, { redirect: mode }); Try / catch
try {
const resp = await fetch(url, { redirect: 'error' });
} catch (e) {
if (String(e).includes('redirect failed')) {
const resp = await fetch(url, { redirect: 'manual' }); // fall back to manual handling
}
} Prevention
- Default to 'follow'; reach for 'error' only to assert a URL is redirect-free
- Resolve short links once during development and store the final URL
- Remember the cap and modes mirror the browser fetch spec
When it happens
Trigger: gopeed.fetch(url, {redirect: 'error'}) where the server answers 301/302/303/307/308; resolving a short link or CDN URL that always redirects to a signed target while redirect mode is 'error'.
Common situations: Extension authors copying browser code that used redirect:'error' to detect hops; sites where the initial resolve URL is a permanent redirect to the canonical host; login flows that redirect to an auth domain.
Related errors
- too many redirects
- Network request timed out
- Network request failed: %w
- redirect failed
- too many redirects
AI-assisted analysis of GopeedLab/gopeed@7b7327ffb3 (2026-08-16).
Data as JSON: /api/errors/58d8c9f75ae62c3c.
Report an issue: GitHub.