chenhg5/cc-connect · error
read response: %w
Error message
read response: %w
What it means
downloadAudio fetched the DingTalk audio file from its download URL but io.ReadAll on the response body failed — connection reset or timeout mid-download. Wraps the read error and aborts audio message handling.
Source
Thrown at platform/dingtalk/dingtalk.go:662
downloadURL, err := p.getDownloadURL(downloadCode)
if err != nil {
return nil, "", fmt.Errorf("get download URL: %w", err)
}
// Download audio file
resp, err := p.httpClient.Get(downloadURL)
if err != nil {
return nil, "", fmt.Errorf("http get: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
return nil, "", fmt.Errorf("download returned status %d", resp.StatusCode)
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, "", fmt.Errorf("read response: %w", err)
}
// Determine MIME type from Content-Type header
mimeType := resp.Header.Get("Content-Type")
if mimeType == "" {
mimeType = "audio/amr" // Default to AMR if not specified
}
return data, mimeType, nil
}
func (p *Platform) getDownloadURL(downloadCode string) (string, error) {
token, err := p.getAccessToken()
if err != nil {
return "", fmt.Errorf("get access token: %w", err)
}
reqBody := map[string]string{View on GitHub (pinned to 4000b2338a)
Solutions
- Retry the download (fetch a fresh URL if needed) — this is usually transient.
- Increase the httpClient timeout if audio files are large.
- Check network stability/proxy idle-timeout settings on the host.
- Log the wrapped cause to confirm whether it's 'unexpected EOF' vs 'context deadline exceeded' and treat accordingly.
Defensive patterns
Strategy: retry
Try / catch
if err != nil {
if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, context.DeadlineExceeded) {
return retryDownload(1) // transient; fetch fresh URL and retry
}
return fmt.Errorf("audio read: %w", err)
} Prevention
- Use an httpClient with an adequate timeout for the expected audio sizes
- Prefer downloading on stable networks; avoid reusing connections through aggressive proxies
- Log whether the failure is EOF vs deadline to pick retry vs alert
When it happens
Trigger: io.ReadAll(resp.Body) in downloadAudio errored while draining the body of the audio download response.
Common situations: Flaky network or CDN closing the connection mid-transfer; HTTP client timeout cutting off a large audio file; proxy killing long-lived connections.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/c7d5f2886da98389.
Report an issue: GitHub.