chenhg5/cc-connect · error
dingtalk: send audio request: %w
Error message
dingtalk: send audio request: %w
What it means
This error wraps a failure from httpClient.Do when executing the audio voice-message request to DingTalk's oToMessages batchSend endpoint. The request was built but the HTTP round trip failed: DNS, connect, TLS, timeout, or context cancellation. No response was received from DingTalk.
Source
Thrown at platform/dingtalk/dingtalk.go:1281
body, err := json.Marshal(requestBody)
if err != nil {
return fmt.Errorf("dingtalk: marshal audio message: %w", err)
}
slog.Debug("dingtalk: sending voice via oToMessages API", "media_id", mediaID, "duration", durationMs, "user_id", rc.senderStaffId)
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
"https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend",
bytes.NewReader(body))
if err != nil {
return fmt.Errorf("dingtalk: create audio request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-acs-dingtalk-access-token", token)
resp, err := p.httpClient.Do(req)
if err != nil {
return fmt.Errorf("dingtalk: send audio request: %w", err)
}
defer func() { _ = resp.Body.Close() }()
respBody, _ := io.ReadAll(resp.Body)
slog.Debug("dingtalk: oToMessages API response", "status", resp.StatusCode, "body", string(respBody))
if resp.StatusCode != 200 {
return fmt.Errorf("dingtalk: send audio failed: status=%d, body=%s", resp.StatusCode, string(respBody))
}
slog.Info("dingtalk: voice message sent successfully", "media_id", mediaID, "conversation_id", rc.conversationId)
return nil
}
// compressAudio compresses audio if it exceeds size limits.
// Uses ffmpeg to convert WAV to MP3 format (DingTalk supported, ~10:1 compression ratio).
func (p *Platform) compressAudio(ctx context.Context, audio []byte, format string) ([]byte, string, error) {
// Only WAV format can be compressed to MP3View on GitHub (pinned to 4000b2338a)
Solutions
- Check the wrapped error: timeout vs connection refused vs context cancelled
- Test connectivity: curl -v https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend
- Increase the httpClient timeout and retry with backoff on transient errors
- Ensure no proxy env vars (HTTP_PROXY/HTTPS_PROXY) interfere with api.dingtalk.com
Example fix
// before
client := &http.Client{Timeout: 5 * time.Second}
// after
client := &http.Client{Timeout: 30 * time.Second}
// plus caller-side retry
var err error
for i := 0; i < 3; i++ { if err = p.SendAudio(ctx, rc, audio, format); err == nil { break }; time.Sleep(time.Duration(1<<i) * time.Second) } Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", "api.dingtalk.com:443", 5*time.Second); if err != nil { /* network unavailable */ } Try / catch
err := p.SendAudio(ctx, rc, audio, format)
if err != nil {
var ne net.Error
if errors.As(err, &ne) && ne.Timeout() { /* retry with backoff */ }
if errors.Is(err, context.Canceled) { /* caller cancelled; don't retry */ }
} Prevention
- Use a 15-30s client timeout for voice message sends
- Implement exponential-backoff retries for transient network errors
- Don't cancel the request context while audio is in flight
- Check HTTP(S)_PROXY settings don't block api.dingtalk.com
When it happens
Trigger: Calling SendAudio when the network to api.dingtalk.com is down, the context is cancelled mid-flight, the HTTP client timeout expires, TLS fails, or a proxy/firewall blocks the connection.
Common situations: Offline or restricted hosts, slow networks timing out during send, VPN/proxy interruptions, upstream engine cancelling the context.
Related errors
- do request: %w
- do request: %w
- dingtalk: emotion request: %w
- dingtalk: send image request: %w
- dingtalk: send file request: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/e1e94e97fc06d6bd.
Report an issue: GitHub.