{"record":{"id":"563272914f5661ac","repo":"chenhg5/cc-connect","slug":"dingtalk-upload-audio-w","errorCode":null,"errorMessage":"dingtalk: upload audio: %w","messagePattern":"dingtalk: upload audio: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/dingtalk.go","lineNumber":1222,"sourceCode":"\n\t// Compress audio if too large (DingTalk limit is 2MB)\n\tconst maxAudioSize = 2 * 1024 * 1024\n\tif len(audio) > maxAudioSize {\n\t\tslog.Debug(\"dingtalk: audio too large, compressing\", \"size\", len(audio), \"max\", maxAudioSize)\n\t\tcompressed, compressedFormat, err := p.compressAudio(ctx, audio, format)\n\t\tif err != nil {\n\t\t\tslog.Warn(\"dingtalk: compression failed, using original\", \"error\", err)\n\t\t} else {\n\t\t\taudio = compressed\n\t\t\tformat = compressedFormat\n\t\t\tslog.Debug(\"dingtalk: audio compressed\", \"new_size\", len(audio), \"new_format\", format)\n\t\t}\n\t}\n\n\t// Upload audio to DingTalk media API\n\tmediaID, err := p.uploadMedia(ctx, audio, fmt.Sprintf(\"audio.%s\", format), \"voice\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: upload audio: %w\", err)\n\t}\n\n\tslog.Debug(\"dingtalk: audio uploaded\", \"media_id\", mediaID, \"format\", format, \"size\", len(audio))\n\n\t// Calculate duration from audio size (rough estimate based on bitrate)\n\t// NOTE: This is an approximation. For accurate duration, consider using ffprobe or go-audio library.\n\t// OGG (Opus 64kbps): ~8KB/sec, AMR-NB (12.2kbps): ~4KB/sec, MP3 (128kbps): ~16KB/sec\n\tvar duration int\n\tif format == \"ogg\" {\n\t\tduration = len(audio) / 8000\n\t} else if format == \"amr\" {\n\t\tduration = len(audio) / 4000\n\t} else if format == \"mp3\" {\n\t\tduration = len(audio) / 16000\n\t} else {\n\t\tduration = len(audio) / 32000\n\t}\n\tif duration == 0 {","sourceCodeStart":1204,"sourceCodeEnd":1240,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/dingtalk.go#L1204-L1240","documentation":"SendAudio uploads the (possibly converted) audio to DingTalk's media upload API via p.uploadMedia to obtain a mediaId; this error wraps any failure of that upload. Without a valid mediaId the voice message cannot be sent.","triggerScenarios":"Calling SendAudio when uploadMedia fails: invalid/expired access token used by upload, network failure to the media endpoint, file exceeding DingTalk's media size limits, wrong media type parameter (\"voice\"), or empty audio bytes.","commonSituations":"Token service outage, audio payload larger than DingTalk's 20MB media limit, empty audio produced by a failed conversion upstream, transient network errors.","solutions":["Check the wrapped error: auth failures → refresh the access token; size errors → compress or split the audio","Validate audio is non-empty before uploading","Verify the converted format is really ogg/amr (extension matches content)","Retry on transient network failures"],"exampleFix":"// before\nmediaID, err := p.uploadMedia(ctx, audio, fmt.Sprintf(\"audio.%s\", format), \"voice\")\n// after\nif len(audio) == 0 { return errors.New(\"dingtalk: empty audio, nothing to upload\") }\nmediaID, err := p.uploadMedia(ctx, audio, fmt.Sprintf(\"audio.%s\", format), \"voice\")","handlingStrategy":"retry","validationCode":"if len(audio) == 0 { return errors.New(\"empty audio\") }\nif len(audio) > 20*1024*1024 { return errors.New(\"audio exceeds DingTalk media size limit\") }","typeGuard":null,"tryCatchPattern":"var lastErr error\nfor i := 0; i < 3; i++ {\n    err := p.SendAudio(ctx, rc, audio, format)\n    if err == nil { return nil }\n    lastErr = err\n    if strings.Contains(err.Error(), \"upload audio\") { time.Sleep(time.Duration(1<<i) * time.Second); continue }\n    return err\n}\nreturn lastErr","preventionTips":["Validate audio size against DingTalk's media limits before upload","Refresh tokens before upload if nearing expiry","Use the correct media type (\"voice\") in uploadMedia calls","Check the conversion output actually matches the declared format/extension"],"tags":["dingtalk","upload","media","audio"],"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-14T00:17:10.932Z"}