larksuite/cli · error
too many redirects
Error message
too many redirects
What it means
This error comes from the CheckRedirect hook installed by NewDownloadHTTPClient in internal/validate/url.go. The download client intentionally limits how many HTTP redirects it will follow for untrusted source URLs; when a server responds with more redirects than opts.MaxRedirects (default 5), the client aborts and the http.Client surfaces 'stopped after N redirects' wrapping this error. It exists to prevent redirect loops and to bound the SSRF/validation surface.
Source
Thrown at internal/validate/url.go:144
// NewDownloadHTTPClient clones base client and enforces download-safe redirect
// and connection rules for untrusted URLs.
func NewDownloadHTTPClient(base *http.Client, opts DownloadHTTPClientOptions) *http.Client {
if base == nil {
base = &http.Client{}
}
if opts.MaxRedirects <= 0 {
opts.MaxRedirects = defaultDownloadMaxRedirects
}
cloned := *base
cloned.Transport = &downloadSchemeTransport{
base: cloneDownloadTransport(base.Transport),
allowHTTP: opts.AllowHTTP,
}
cloned.CheckRedirect = func(req *http.Request, via []*http.Request) error {
if len(via) >= opts.MaxRedirects {
return fmt.Errorf("too many redirects")
}
if len(via) > 0 {
prev := via[len(via)-1]
if strings.EqualFold(prev.URL.Scheme, "https") && strings.EqualFold(req.URL.Scheme, "http") {
return fmt.Errorf("redirect from https to http is not allowed")
}
}
if !opts.AllowHTTP && !strings.EqualFold(req.URL.Scheme, "https") {
return fmt.Errorf("only https URLs are supported")
}
if err := ValidateDownloadSourceURL(req.Context(), req.URL.String()); err != nil {
return fmt.Errorf("blocked redirect target: %w", err)
}
return nil
}
return &cloned
}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Raise MaxRedirects in DownloadHTTPClientOptions when constructing the client (values <=0 fall back to the default of 5).
- Resolve the final URL manually (follow redirects with a plain client or inspect Location headers) and download the terminal URL directly.
- If it is a redirect loop, fix or avoid the source URL; no client option will make a looping server converge.
Example fix
// before
client := validate.NewDownloadHTTPClient(base, validate.DownloadHTTPClientOptions{})
// after (allow longer legitimate redirect chains)
client := validate.NewDownloadHTTPClient(base, validate.DownloadHTTPClientOptions{MaxRedirects: 10}) Defensive patterns
Strategy: try-catch
Validate before calling
u, err := url.Parse(src)
if err != nil || u.Scheme == "" {
return fmt.Errorf("invalid download URL")
}
// Optionally pre-follow with a probe to detect loops before the real download. Try / catch
resp, err := client.Get(url)
if err != nil {
if strings.Contains(err.Error(), "too many redirects") {
// treat source as unreliable: surface a clear message or try mirror
return fmt.Errorf("download source redirect loop or chain too long: %w", err)
}
return err
} Prevention
- Set MaxRedirects explicitly to match known endpoint redirect depth instead of relying on the default of 5.
- Test download sources once at setup time to catch redirect loops early.
- Prefer direct canonical URLs (CDN/final destination) over endpoints that bounce.
When it happens
Trigger: Any download via a client built by NewDownloadHTTPClient where the target host responds with a 3xx chain longer than opts.MaxRedirects (default 5), including redirect loops where a server redirects back to itself or bounces between two URLs.
Common situations: Downloading from a misconfigured host whose http->https redirect points back to http (infinite loop); CDN or auth endpoints with long redirect chains; a caller setting MaxRedirects too low (e.g. 1-2) while the legit endpoint bounces a few times.
Related errors
- redirect from https to http is not allowed
- only https URLs are supported
- app registration failed: HTTP %d – response not JSON
- Device authorization failed: read body: %v
- failed to read response body in security transport: %w
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/d57334462720e19a.
Report an issue: GitHub.