{"record":{"id":"782b5d18d0a07a3d","repo":"chenhg5/cc-connect","slug":"weixin-s-w-782b5d","errorCode":null,"errorMessage":"weixin: %s: %w","messagePattern":"weixin: (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/weixin/media_outbound.go","lineNumber":80,"sourceCode":"\trawSize := len(plaintext)\n\taesKey := make([]byte, 16)\n\tif _, err := rand.Read(aesKey); err != nil {\n\t\treturn nil, fmt.Errorf(\"weixin: %s: aes key: %w\", label, err)\n\t}\n\tfilekey := randomHex(16)\n\treq := getUploadURLRequest{\n\t\tFilekey:     filekey,\n\t\tMediaType:   mediaType,\n\t\tToUserID:    to,\n\t\tRawsize:     rawSize,\n\t\tRawfilemd5:  md5Hex(plaintext),\n\t\tFilesize:    aesECBPaddedSize(rawSize),\n\t\tNoNeedThumb: true,\n\t\tAeskey:      hex.EncodeToString(aesKey),\n\t}\n\tresp, err := p.api.getUploadURL(ctx, req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"weixin: %s: %w\", label, err)\n\t}\n\t// 选择上传 URL 和 HTTP client\n\tvar cdnUploadURL string\n\tvar uploadClient *http.Client\n\tif resp.UploadFullURL != \"\" {\n\t\t// 新版 API：使用服务端返回的完整 URL\n\t\tcdnUploadURL = resp.UploadFullURL\n\t\t// 如果 URL 指向已知的微信国内 CDN，使用无代理 client 直连\n\t\tif isWeixinCDNHost(cdnUploadURL) {\n\t\t\tuploadClient = p.cdnHttpClient\n\t\t} else {\n\t\t\tuploadClient = p.httpClient\n\t\t}\n\t} else {\n\t\t// 旧版 API：用 upload_param 构建 URL，使用配置的 httpClient\n\t\tcdnUploadURL = buildCdnUploadURL(p.cdnBaseURL, resp.UploadParam, filekey)\n\t\tuploadClient = p.httpClient\n\t}","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/weixin/media_outbound.go#L62-L98","documentation":"The getUploadURL API call to obtain a CDN upload URL failed; uploadToWeixinCDN wraps the underlying error with the operation label. This is the WeChat/ilink API layer rejecting or failing the upload-authorization request.","triggerScenarios":"Network failure, auth token invalid/expired, server error, or API-level ret code returned by p.api.getUploadURL during SendImage/SendFile/SendAudio.","commonSituations":"Expired WeChat session/credentials; ilink server rejecting the request (rate-limit, bad peer); DNS or proxy failure in the deployment environment.","solutions":["Unwrap and inspect the wrapped error (%w) to see the root cause (auth vs network vs API ret code).","Re-authenticate / refresh the WeChat session credentials if the error indicates expired auth.","Check network connectivity and proxy settings from the host to the WeChat API endpoint.","If the wrapped error is the ilink ret=-2 throttle, wait and retry later."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := p.SendImage(ctx, rc, img); err != nil {\n    var apiErr *weixin.APIError\n    if errors.As(err, &apiErr) { handleAPIRet(apiErr.Ret) }\n    else if isSendThrottled(err) { scheduleRetry(err) }\n    else { log.Error(\"upload URL fetch failed\", \"err\", err) }\n}","preventionTips":["Keep WeChat session credentials fresh","Monitor connectivity to the WeChat API endpoint","Unwrap %w errors to classify root causes","Respect ret=-2 throttles with long backoff"],"tags":["weixin","media","api","network"],"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"}