{"record":{"id":"3783031c9c9c68f7","repo":"chenhg5/cc-connect","slug":"dingtalk-marshal-audio-message-w","errorCode":null,"errorMessage":"dingtalk: marshal audio message: %w","messagePattern":"dingtalk: marshal audio message: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/dingtalk.go","lineNumber":1265,"sourceCode":"\t// This is the official API for sending voice messages in bot conversations\n\ttoken, err := p.getAccessToken()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: get access token: %w\", err)\n\t}\n\n\t// Build oToMessages API request with sampleAudio msgKey\n\t// msgParam must be a JSON string, not an object\n\tmsgParamJSON := fmt.Sprintf(`{\"mediaId\":\"%s\",\"duration\":\"%d\"}`, mediaID, durationMs)\n\trequestBody := map[string]interface{}{\n\t\t\"robotCode\": p.robotCode,\n\t\t\"userIds\":   []string{rc.senderStaffId},\n\t\t\"msgKey\":    \"sampleAudio\",\n\t\t\"msgParam\":  msgParamJSON,\n\t}\n\n\tbody, err := json.Marshal(requestBody)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: marshal audio message: %w\", err)\n\t}\n\n\tslog.Debug(\"dingtalk: sending voice via oToMessages API\", \"media_id\", mediaID, \"duration\", durationMs, \"user_id\", rc.senderStaffId)\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost,\n\t\t\"https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend\",\n\t\tbytes.NewReader(body))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: create audio request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"x-acs-dingtalk-access-token\", token)\n\n\tresp, err := p.httpClient.Do(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: send audio request: %w\", err)\n\t}\n\tdefer func() { _ = resp.Body.Close() }()","sourceCodeStart":1247,"sourceCodeEnd":1283,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/dingtalk.go#L1247-L1283","documentation":"SendAudio builds the oToMessages request body as a map and serializes it with json.Marshal; this error wraps a marshal failure. With the fixed string keys and primitive values used here (strings, an int duration), marshaling essentially cannot fail in normal operation — it is a defensive guard. Seeing it indicates corrupted data types or memory pressure.","triggerScenarios":"Calling SendAudio when json.Marshal fails on the requestBody map — practically only via abnormal values (e.g. someone placing an unmarshalable type like a channel or NaN in the map after code changes) or extreme memory conditions.","commonSituations":"Essentially never in production with stock code; appears after modifications to requestBody that add unsupported value types.","solutions":["Inspect the wrapped error for the unmarshalable type","Ensure all values in requestBody are JSON-encodable primitives","Report a bug if it reproduces with unmodified code"],"exampleFix":"// before\nrequestBody := map[string]interface{}{\"robotCode\": code, \"userIds\": userIds, \"msgKey\": \"sampleAudio\", \"msgParam\": msgParamJSON}\n// after — keep values as JSON-safe types; avoid channel/func/NaN values\nrequestBody := map[string]any{\"robotCode\": code, \"userIds\": []string{uid}, \"msgKey\": \"sampleAudio\", \"msgParam\": msgParamJSON}","handlingStrategy":"try-catch","validationCode":"// ensure all map values are JSON-encodable primitives\nfor k, v := range requestBody { if !isJSONSafe(v) { return fmt.Errorf(\"non-JSON-safe value at %s\", k) } }","typeGuard":null,"tryCatchPattern":"if err := p.SendAudio(ctx, rc, audio, format); err != nil && strings.Contains(err.Error(), \"marshal audio message\") { log.Fatalf(\"non-JSON-encodable value in request body: %v\", err) }","preventionTips":["Keep requestBody values limited to strings, ints, and slices of strings","Use typed structs instead of map[string]interface{} to catch issues at compile time","Treat this error as a code bug and file a report if it occurs"],"tags":["dingtalk","json","marshal"],"backgroundTag":"json-marshal-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}