chenhg5/cc-connect · warning

remote image HTTP status %d

Error message

remote image HTTP status %d

What it means

When fetching a remote image for a rich (interactive) card, the HTTP response status was outside 2xx. The download is aborted because the body won't contain a usable image. SSRF-safe fetching (custom dialer) still allows any public host, so remote servers can 404/403.

Source

Thrown at platform/feishu/feishu.go:6622

	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
	}
	defer func() {
		if err := resp.Body.Close(); err != nil {
			slog.Debug("feishu: close rich card image response body", "error", err)
		}
	}()

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return nil, "", fmt.Errorf("remote image HTTP status %d", resp.StatusCode)
	}
	if resp.ContentLength > richCardImageMaxBytes {
		return nil, "", fmt.Errorf("remote image too large: %d bytes", resp.ContentLength)
	}

	data, err := io.ReadAll(io.LimitReader(resp.Body, richCardImageMaxBytes+1))
	if err != nil {
		return nil, "", err
	}
	if len(data) > richCardImageMaxBytes {
		return nil, "", fmt.Errorf("remote image exceeds %d bytes", richCardImageMaxBytes)
	}
	mimeType := http.DetectContentType(data)
	if !isSupportedRichCardImageMIME(mimeType) {
		return nil, "", fmt.Errorf("unsupported remote image MIME %q", mimeType)
	}
	return data, mimeType, nil
}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Verify the image URL is publicly reachable (curl -I the URL)
  2. Re-generate/re-sign the image URL if it contains an expiring token
  3. Add a standard User-Agent if the remote host blocks non-browser clients
  4. Implement a fallback: catch this error and send the card without the image or with a placeholder
  5. Cache images so transient 5xx don't break card rendering

Example fix

// caller
img, mime, err := fetchRemoteImage(ctx, url)
if err != nil {
    slog.Warn("image fetch failed, using placeholder", "err", err)
    img, mime = placeholderImage, "image/png"
}
Defensive patterns

Strategy: fallback

Validate before calling

resp, err := http.Head(imageURL); if err != nil || resp.StatusCode < 200 || resp.StatusCode >= 300 { /* use fallback image */ }

Try / catch

img, mime, err := fetchRemoteImage(ctx, url)
if err != nil {
    slog.Warn("remote image unavailable, using placeholder", "err", err)
    img, mime = placeholderPNG, "image/png"
}

Prevention

When it happens

Trigger: Downloading an image URL referenced by a card and the remote server returns 404 (image moved/deleted), 403 (hotlink protection/auth), 5xx, or a redirect loop ending in non-2xx.

Common situations: Expired CDN links; images behind auth tokens that expired; hotlink protection blocking the bot's user agent; DNS pointing at a server that returns errors.

Related errors


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