chenhg5/cc-connect · warning
too many redirects
Error message
too many redirects
What it means
The rich-card image fetcher limits redirect chains to 3 hops via http.Client's CheckRedirect. When a URL redirects more than twice, it returns this error to stop infinite/long redirect loops, which also serves as SSRF protection since each hop is re-validated. The http.Client then surfaces it wrapped in url.Error.
Source
Thrown at platform/feishu/feishu.go:6596
}
return u.Hostname()
}
func fetchRichCardRemoteImage(ctx context.Context, rawURL string) ([]byte, string, error) {
u, err := url.Parse(rawURL)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") || u.Host == "" {
return nil, "", errors.New("invalid remote image URL")
}
client := &http.Client{
Timeout: richCardImageFinalWait,
Transport: &http.Transport{
DialContext: dialPublicRichCardImageContext,
ResponseHeaderTimeout: richCardImageFinalWait,
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) >= 3 {
return errors.New("too many redirects")
}
if !isRemoteRichCardImageURL(req.URL.String()) {
return errors.New("redirected to unsupported image URL")
}
return nil
},
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil)
if err != nil {
return nil, "", err
}
req.Header.Set("User-Agent", "cc-connect-feishu-rich-card-image-resolver/1.0")
resp, err := client.Do(req)
if err != nil {
return nil, "", err
}View on GitHub (pinned to 4000b2338a)
Solutions
- Use a direct, non-redirecting image URL (the final destination after following redirects manually).
- Pre-resolve the redirect chain once and store the final URL.
- Ask the content provider to fix the redirect loop; verify the URL with curl -IL to count hops.
Example fix
// before
card.ImageURL = "https://shortener.example.com/img/abc123"
// after
finalURL := resolveRedirects("https://shortener.example.com/img/abc123") // follow once at ingestion time
card.ImageURL = finalURL Defensive patterns
Strategy: fallback
Validate before calling
client := &http.Client{CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) >= 3 { return errors.New("too many redirects") }
return nil
}}
// HEAD the URL first to count hops before card rendering Try / catch
var urlErr *url.Error
if errors.As(err, &urlErr) && strings.Contains(urlErr.Err.Error(), "too many redirects") {
// use a cached/proxied copy of the image instead
} Prevention
- Prefer direct CDN URLs over shorteners in generated card content.
- Resolve shortener chains once at ingestion and store the final URL.
- Cache successfully fetched images and reuse them instead of refetching redirecting URLs.
When it happens
Trigger: Fetching a rich card image whose server issues a >=3-deep redirect chain (platform/feishu/feishu.go:6596); also triggered when any redirect hop fails the isRemoteRichCardImageURL re-validation, though that yields the redirect-target error instead.
Common situations: Image CDN behind multiple chained redirects (auth -> geo -> CDN); redirect loops caused by misconfigured servers; shortener services that redirect several times; expired URLs redirecting to login pages repeatedly.
Related errors
- remote image HTTP status %d
- remote image too large: %d bytes
- remote image exceeds %d bytes
- invalid remote image URL
- redirected to unsupported image URL
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/d8d9f9f263adfb8e.
Report an issue: GitHub.