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

  1. Check available memory if media files are large; compress before upload (the WAV→MP3 path already reduces size ~10:1).
  2. Ensure data is the complete output of upload/compression and not an empty/truncated slice.
  3. 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

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/6935b5ba233572ea. Report an issue: GitHub.