chenhg5/cc-connect · error
close multipart writer: %w
Error message
close multipart writer: %w
What it means
multipart.Writer.Close() failed when finalizing the upload body for the DingTalk media API. Close flushes the closing boundary; failure here means the multipart body is incomplete and the request must not be sent.
Source
Thrown at platform/dingtalk/dingtalk.go:1360
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() }()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("read upload response: %w", err)View on GitHub (pinned to 4000b2338a)
Solutions
- Ensure Close is called exactly once, after all parts are written.
- If Close fails, abandon the body and rebuild it — a half-closed multipart body yields server-side parse errors.
- For large media, write to a temp file sink instead of an in-memory buffer to avoid allocation failures.
Example fix
// before
defer writer.Close()
...
req, _ := http.NewRequestWithContext(ctx, "POST", uploadURL, body) // may race Close
// after
if err := writer.Close(); err != nil { return "", fmt.Errorf("close multipart writer: %w", err) }
req, err := http.NewRequestWithContext(ctx, http.MethodPost, uploadURL, body) Defensive patterns
Strategy: try-catch
Try / catch
if err := writer.Close(); err != nil {
return "", fmt.Errorf("close multipart writer: %w", err) // do NOT send the request
} Prevention
- Call Close exactly once, after all parts, and check its error before building the request.
- Never defer Close when the result gates whether the request is sent.
- Rebuild the body from scratch if Close fails.
When it happens
Trigger: writer.Close() returns an error in uploadMedia after all parts were written — typically an underlying buffer write failure or calling Close after the writer was already closed.
Common situations: Double-Close after a refactor; memory pressure on huge media bodies; custom io.Writer sink that errors on flush.
Related errors
- create form file: %w
- write media data: %w
- dingtalk: upload image: %w
- dingtalk: upload audio: %w
- create upload request: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/bb93e81b163d62e4.
Report an issue: GitHub.