chenhg5/cc-connect · error
write media data: %w
Error message
write media data: %w
What it means
Writing the raw media bytes into the multipart form field failed while assembling the upload body. Since the sink is an in-memory bytes.Buffer, this only fires on buffer write errors (e.g. allocation failure) or an internal writer-state problem, but it guards against sending a truncated media payload.
Source
Thrown at platform/dingtalk/dingtalk.go:1356
// mediaType should be "voice" or "image".
func (p *Platform) uploadMedia(ctx context.Context, data []byte, fileName, mediaType string) (string, error) {
token, err := p.getAccessToken()
if err != nil {
return "", fmt.Errorf("get access token: %w", err)
}
uploadURL := fmt.Sprintf("https://oapi.dingtalk.com/media/upload?access_token=%s&type=%s", token, mediaType)
body := bytes.NewBuffer(nil)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("media", fileName)
if err != nil {
return "", fmt.Errorf("create form file: %w", err)
}
if _, err := part.Write(data); err != nil {
return "", fmt.Errorf("write media data: %w", err)
}
if err := writer.Close(); err != nil {
return "", fmt.Errorf("close multipart writer: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, uploadURL, body)
if err != nil {
return "", fmt.Errorf("create upload request: %w", err)
}
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := p.httpClient.Do(req)
if err != nil {
return "", fmt.Errorf("upload request: %w", err)
}
defer func() { _ = resp.Body.Close() }()View on GitHub (pinned to 4000b2338a)
Solutions
- Check available memory if media files are large; compress before upload (the WAV→MP3 path already reduces size ~10:1).
- Ensure data is the complete output of upload/compression and not an empty/truncated slice.
- Build the multipart body once per upload in a single goroutine; never share buffers across requests.
Example fix
// before
audio, _, err := p.compressAudio(ctx, raw, "wav")
_ = err
mediaID, err := p.uploadMedia(ctx, audio, ...) // audio may be nil
// after
if err != nil || len(audio) == 0 { return fmt.Errorf("compress audio: %w", err) } Defensive patterns
Strategy: validation
Validate before calling
if len(data) == 0 { return errors.New("empty media payload") }
if len(data) > maxMediaSize { return fmt.Errorf("media too large: %d bytes", len(data)) } Prevention
- Check the payload is complete and non-empty before upload.
- Compress large audio (WAV→MP3) to shrink the in-memory buffer.
- Guard buffer/memory usage for large media; consider a file-backed sink.
When it happens
Trigger: part.Write(data) returns n < len(data) or an error inside uploadMedia while writing the file content for the DingTalk media/upload request.
Common situations: Very large audio blobs causing memory pressure/OOM on small hosts; concurrent mutation of the bytes.Buffer; passing a nil or already-consumed data slice after upstream compression failed silently.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- create form file: %w
- close multipart writer: %w
- read upload response: %w
- read response: %w
- dingtalk: upload image: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/6935b5ba233572ea.
Report an issue: GitHub.