{"record":{"id":"39aecfcd3eb1f50d","repo":"chenhg5/cc-connect","slug":"decode-upload-finish-response-w","errorCode":null,"errorMessage":"decode upload finish response: %w","messagePattern":"decode upload finish response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wecom/websocket_outbound_media.go","lineNumber":117,"sourceCode":"\t}\n\n\tfinishReqID := p.generateReqID(\"aibot_upload_media_finish\")\n\tfinishFrame := map[string]any{\n\t\t\"cmd\":     \"aibot_upload_media_finish\",\n\t\t\"headers\": map[string]string{\"req_id\": finishReqID},\n\t\t\"body\": map[string]any{\n\t\t\t\"upload_id\": initBody.UploadID,\n\t\t},\n\t}\n\tfinishResp, err := p.writeAndWaitFrameWithTimeout(ctx, finishFrame, finishReqID, wsMediaAckTimeout)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"upload finish: %w\", err)\n\t}\n\tvar finishBody struct {\n\t\tMediaID string `json:\"media_id\"`\n\t}\n\tif err := json.Unmarshal(finishResp.Body, &finishBody); err != nil {\n\t\treturn \"\", fmt.Errorf(\"decode upload finish response: %w\", err)\n\t}\n\tif finishBody.MediaID == \"\" {\n\t\treturn \"\", fmt.Errorf(\"upload finish: empty media_id\")\n\t}\n\treturn finishBody.MediaID, nil\n}\n\nfunc (p *WSPlatform) sendWSMediaMessage(ctx context.Context, chatID, mediaType, mediaID string) error {\n\treqID := p.generateReqID(\"aibot_send_msg\")\n\tframe := map[string]any{\n\t\t\"cmd\":     \"aibot_send_msg\",\n\t\t\"headers\": map[string]string{\"req_id\": reqID},\n\t\t\"body\": map[string]any{\n\t\t\t\"chatid\":  chatID,\n\t\t\t\"msgtype\": mediaType,\n\t\t\tmediaType: map[string]string{\n\t\t\t\t\"media_id\": mediaID,\n\t\t\t},","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wecom/websocket_outbound_media.go#L99-L135","documentation":"The aibot_upload_media_finish ack arrived but its body could not be parsed as JSON containing a 'media_id' field. This indicates the server returned an unexpected body — often an error payload or a protocol version mismatch rather than the expected {\"media_id\":\"...\"} shape.","triggerScenarios":"Called from SendImage/SendFile via uploadWSMedia when json.Unmarshal(finishResp.Body, &finishBody) fails after a successful finish ack.","commonSituations":"WeCom API version changed the finish response schema; the server returned an error JSON (different fields) with a 200-style ack; a gateway/proxy substituted an HTML or text error body.","solutions":["Log finishResp.Body verbatim to see what the server actually returned","Check for an embedded error code/message in the body and surface it instead of the raw unmarshal error","Update the finishBody struct to match the current WeCom AI Bot API response schema","Confirm you are on a supported WeCom AI Bot protocol version"],"exampleFix":"// before\nif err := json.Unmarshal(finishResp.Body, &finishBody); err != nil {\n\treturn \"\", fmt.Errorf(\"decode upload finish response: %w\", err)\n}\n// after\nif err := json.Unmarshal(finishResp.Body, &finishBody); err != nil {\n\treturn \"\", fmt.Errorf(\"decode upload finish response %s: %w\", string(finishResp.Body), err)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isValidFinishBody(b []byte) bool {\n\tvar probe struct {\n\t\tMediaID string `json:\"media_id\"`\n\t}\n\treturn json.Unmarshal(b, &probe) == nil\n}","tryCatchPattern":"mediaID, err := p.SendFile(ctx, rc, file)\nif err != nil && strings.Contains(err.Error(), \"decode upload finish response\") {\n\tlog.Error(\"unexpected finish ack\", \"err\", err) // inspect server body in logs\n}","preventionTips":["Log raw response bodies for protocol errors","Pin/track the WeCom AI Bot API version you integrate against","Add a schema smoke test for the finish response shape"],"tags":["json","unmarshal","websocket","api-response"],"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"}