{"record":{"id":"693bc186de0d60b4","repo":"chenhg5/cc-connect","slug":"weixin-getuploadurl-json-w","errorCode":null,"errorMessage":"weixin: getUploadUrl json: %w","messagePattern":"weixin: getUploadUrl json: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/weixin/client.go","lineNumber":204,"sourceCode":"\t\treturn fmt.Errorf(\"weixin: sendMessage: ret=%d errcode=%d errmsg=%s\",\n\t\t\tresp.Ret, resp.Errcode, resp.Errmsg)\n\t}\n\treturn nil\n}\n\nfunc (c *apiClient) getUploadURL(ctx context.Context, req getUploadURLRequest) (*getUploadURLResponse, error) {\n\treq.BaseInfo = baseInfo{ChannelVersion: channelVersion}\n\tpayload, err := json.Marshal(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\traw, err := c.post(ctx, \"ilink/bot/getuploadurl\", payload, 0, \"getUploadUrl\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar out getUploadURLResponse\n\tif err := json.Unmarshal(raw, &out); err != nil {\n\t\treturn nil, fmt.Errorf(\"weixin: getUploadUrl json: %w\", err)\n\t}\n\t// 兼容微信 iLink API 变更：新版返回 upload_full_url 而非 upload_param\n\t// upload_full_url 是完整的 CDN 上传地址，可独立作为成功路径\n\tif strings.TrimSpace(out.UploadParam) == \"\" && strings.TrimSpace(out.UploadFullURL) == \"\" {\n\t\treturn nil, fmt.Errorf(\"weixin: getUploadUrl: empty upload_param and upload_full_url in %s\", truncateForLog(raw, 512))\n\t}\n\treturn &out, nil\n}\n\nfunc (c *apiClient) getConfig(ctx context.Context, userID, contextToken string) (*getConfigResp, error) {\n\treq := getConfigReq{\n\t\tUserID:       userID,\n\t\tContextToken: contextToken,\n\t\tBaseInfo:     baseInfo{ChannelVersion: channelVersion},\n\t}\n\tpayload, err := json.Marshal(req)\n\tif err != nil {\n\t\treturn nil, err","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/weixin/client.go#L186-L222","documentation":"getUploadURL requests a CDN upload address via ilink/bot/getuploadurl and decodes the reply into getUploadURLResponse. This error wraps a json.Unmarshal failure — the body is not valid JSON or does not fit the struct, typically an HTML error page or an API schema change.","triggerScenarios":"The getuploadurl endpoint returns non-JSON (proxy HTML, gateway error) or a new schema whose fields no longer decode into getUploadURLResponse (e.g. type changes causing UnmarshalTypeError).","commonSituations":"WeChat iLink API evolution (the code already works around upload_param→upload_full_url); proxies rewriting responses; authenticated session expired so the server returns an error page.","solutions":["Log the raw body (truncateForLog) to see what was returned","Verify the bot session is valid and re-authenticate","Update getUploadURLResponse to the current iLink schema","Check for intermediaries (proxy/WAF) corrupting the response"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if len(bytes.TrimSpace(raw)) == 0 { return errors.New(\"weixin: empty getuploadurl body\") }","typeGuard":null,"tryCatchPattern":"resp, err := getUploadURL(ctx, req)\nif err != nil {\n\tif strings.Contains(err.Error(), \"getUploadUrl json\") {\n\t\tslog.Error(\"weixin: upload-url response not JSON\", \"err\", err)\n\t\treturn fallbackUploadPath()\n\t}\n\treturn err\n}","preventionTips":["Keep getUploadURLResponse fields updated with iLink API changes","Re-authenticate when uploads suddenly fail with unmarshal errors","Log raw bodies (truncated) for every upload failure"],"tags":["weixin","json","unmarshal","upload"],"backgroundTag":"json-unmarshal-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"}