chenhg5/cc-connect · error
%s: CDN upload server error: %s
Error message
%s: CDN upload server error: %s
What it means
uploadBufferToCDN records this error when the CDN returns a 5xx (or any non-200 outside 400-499) status. It is stored as lastErr and the loop retries up to cdnUploadMaxRetries (3) attempts before surfacing the wrapped error via the 'failed after N attempts' message. The reason is taken from the x-error-message header or 'status <code>'.
Source
Thrown at platform/weixin/cdn.go:210
lastErr = err
slog.Warn("weixin: CDN upload request failed", "label", label, "attempt", attempt, "error", err)
continue
}
_, _ = io.Copy(io.Discard, io.LimitReader(resp.Body, 4096))
_ = resp.Body.Close()
if resp.StatusCode >= 400 && resp.StatusCode < 500 {
msg := resp.Header.Get("x-error-message")
if msg == "" {
msg = resp.Status
}
return "", fmt.Errorf("%s: CDN upload client error %d: %s", label, resp.StatusCode, msg)
}
if resp.StatusCode != http.StatusOK {
msg := resp.Header.Get("x-error-message")
if msg == "" {
msg = fmt.Sprintf("status %d", resp.StatusCode)
}
lastErr = fmt.Errorf("%s: CDN upload server error: %s", label, msg)
slog.Warn("weixin: CDN upload server error", "label", label, "attempt", attempt, "error", lastErr)
continue
}
dl := resp.Header.Get("x-encrypted-param")
if dl == "" {
lastErr = fmt.Errorf("%s: CDN response missing x-encrypted-param", label)
slog.Warn("weixin: CDN upload bad response", "label", label, "attempt", attempt)
continue
}
return dl, nil
}
if lastErr != nil {
return "", fmt.Errorf("%s: CDN upload failed after %d attempts: %w", label, cdnUploadMaxRetries, lastErr)
}
return "", fmt.Errorf("%s: CDN upload failed after %d attempts", label, cdnUploadMaxRetries)
}
func md5Hex(b []byte) string {View on GitHub (pinned to 4000b2338a)
Solutions
- Retry the operation — server errors are transient and the function already retries 3 times; the wrapped lastErr shows the final reason
- Check the x-error-message/status in the error text for the specific 5xx code
- Verify network connectivity and DNS resolution to the CDN host
- If persistent, check WeChat service status or reduce media size/frequency
Example fix
// before: treating every upload failure as fatal
if err := uploadToWeixinCDN(ctx, ...); err != nil { return err }
// after: tolerate transient server errors with backoff at the caller
if err := uploadToWeixinCDN(ctx, ...); err != nil {
if strings.Contains(err.Error(), "server error") { time.Sleep(time.Second); return uploadToWeixinCDN(ctx, ...) }
return err
} Defensive patterns
Strategy: retry
Validate before calling
// check reachability before a batch of uploads
resp, err := http.Get("https://novac2c.cdn.weixin.qq.com/c2c/healthz") // or any cheap probe
if err != nil { /* defer uploads or use fallback */ } Try / catch
// the library already retries 3x; add caller backoff
if err != nil && strings.Contains(err.Error(), "CDN upload server error") {
time.Sleep(2 * time.Second)
// retry once more
} Prevention
- Treat 5xx as transient and add exponential backoff at the call site
- Spread large media uploads over time to avoid CDN-side throttling
- Monitor for repeated server errors and alert on sustained CDN degradation
- Keep the official cdn_base so requests hit healthy endpoints
When it happens
Trigger: Any CDN upload POST returning HTTP >= 500 (or non-200 outside 400-499), e.g. 500, 502, 503 from the CDN edge; each attempt logs slog.Warn then continues.
Common situations: Transient CDN outages or capacity issues; CDN edge nodes returning 502/504; maintenance windows on novac2c.cdn.weixin.qq.com.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- range status %d body=%q
- %s: CDN upload client error %d: %s
- range chunk retries exhausted
- reasonix: POST %s returned %d: %s
- cloud_web: events HTTP %d: %s
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/1b0804a7e5421784.
Report an issue: GitHub.