{"record":{"id":"33e569032039df24","repo":"chenhg5/cc-connect","slug":"s-cdn-upload-failed-after-d-attempts-w","errorCode":null,"errorMessage":"%s: CDN upload failed after %d attempts: %w","messagePattern":"(.+?): CDN upload failed after (.+?) attempts: %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/weixin/cdn.go","lineNumber":223,"sourceCode":"\t\tif resp.StatusCode != http.StatusOK {\n\t\t\tmsg := resp.Header.Get(\"x-error-message\")\n\t\t\tif msg == \"\" {\n\t\t\t\tmsg = fmt.Sprintf(\"status %d\", resp.StatusCode)\n\t\t\t}\n\t\t\tlastErr = fmt.Errorf(\"%s: CDN upload server error: %s\", label, msg)\n\t\t\tslog.Warn(\"weixin: CDN upload server error\", \"label\", label, \"attempt\", attempt, \"error\", lastErr)\n\t\t\tcontinue\n\t\t}\n\t\tdl := resp.Header.Get(\"x-encrypted-param\")\n\t\tif dl == \"\" {\n\t\t\tlastErr = fmt.Errorf(\"%s: CDN response missing x-encrypted-param\", label)\n\t\t\tslog.Warn(\"weixin: CDN upload bad response\", \"label\", label, \"attempt\", attempt)\n\t\t\tcontinue\n\t\t}\n\t\treturn dl, nil\n\t}\n\tif lastErr != nil {\n\t\treturn \"\", fmt.Errorf(\"%s: CDN upload failed after %d attempts: %w\", label, cdnUploadMaxRetries, lastErr)\n\t}\n\treturn \"\", fmt.Errorf(\"%s: CDN upload failed after %d attempts\", label, cdnUploadMaxRetries)\n}\n\nfunc md5Hex(b []byte) string {\n\th := md5.Sum(b)\n\treturn hex.EncodeToString(h[:])\n}\n\nfunc detectImageMime(b []byte) string {\n\tif len(b) >= 3 && b[0] == 0xFF && b[1] == 0xD8 && b[2] == 0xFF {\n\t\treturn \"image/jpeg\"\n\t}\n\tif len(b) >= 8 && string(b[0:8]) == \"\\x89PNG\\r\\n\\x1a\\n\" {\n\t\treturn \"image/png\"\n\t}\n\tif len(b) >= 6 && (string(b[0:6]) == \"GIF87a\" || string(b[0:6]) == \"GIF89a\") {\n\t\treturn \"image/gif\"","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/weixin/cdn.go#L205-L241","documentation":"Final error returned by uploadBufferToCDN after exhausting cdnUploadMaxRetries (3) attempts. It wraps the last underlying failure (lastErr) — a transport error, 5xx server error, or missing x-encrypted-param — so the root cause appears after 'attempts:'.","triggerScenarios":"All 3 upload attempts failed with retryable errors: client.Do transport failures, HTTP >= 500, or 200 responses missing x-encrypted-param.","commonSituations":"Sustained CDN outage; network partition between the bot host and novac2c.cdn.weixin.qq.com; persistent response-contract mismatch (every 200 lacks the header).","solutions":["Read the wrapped %w cause after 'attempts:' to see the actual failure (transport vs server error vs missing header)","If it's a network error, check connectivity/DNS/proxy to the CDN host and retry later","If it's 'server error', wait for the CDN side to recover or add caller-level backoff with longer delays","If it's 'missing x-encrypted-param' on every attempt, verify cdn_base configuration and API-version compatibility"],"exampleFix":"// before: no caller backoff\nerr := uploadToWeixinCDN(ctx, data, key)\n// after: exponential backoff around the 3 built-in attempts\nvar err error\nfor d := time.Second; d <= 8*time.Second; d *= 2 {\n    if err = uploadToWeixinCDN(ctx, data, key); err == nil { break }\n    time.Sleep(d)\n}","handlingStrategy":"retry","validationCode":"// pre-flight network sanity check before large uploads\nif _, err := net.LookupHost(\"novac2c.cdn.weixin.qq.com\"); err != nil { /* postpone upload */ }","typeGuard":null,"tryCatchPattern":"var err error\nfor d := time.Second; d <= 8*time.Second; d *= 2 {\n    if err = uploadToWeixinCDN(ctx, data, key); err == nil { break }\n    time.Sleep(d)\n}\nif err != nil { log.Printf(\"upload permanently failed: %v\", err) }","preventionTips":["Run uploads on hosts with stable connectivity to the CDN","Parse the wrapped cause after 'attempts:' to route fixes (network vs server vs contract)","Queue and retry media uploads in the background instead of failing user messages synchronously","Cap media size well under 100 MiB to reduce upload failure windows"],"tags":["cdn","upload","retry-exhausted","network","weixin"],"backgroundTag":"api-request-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}