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

  1. Use a direct, non-redirecting image URL (the final destination after following redirects manually).
  2. Pre-resolve the redirect chain once and store the final URL.
  3. 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

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/d8d9f9f263adfb8e. Report an issue: GitHub.