valyala/fasthttp · error
error when closing multipart form writer: %w
Error message
error when closing multipart form writer: %w
What it means
fasthttp wraps the error returned by multipart.Writer.Close when finalizing a multipart/form-data body (writing the terminating boundary). Failure means the encoded body is incomplete and the request cannot be sent correctly.
Source
Thrown at http.go:1264
if err != nil {
return fmt.Errorf("cannot create form file %q (%q): %w", k, fv.Filename, err)
}
fh, err := fv.Open()
if err != nil {
return fmt.Errorf("cannot open form file %q (%q): %w", k, fv.Filename, err)
}
if _, err = copyZeroAlloc(vw, fh); err != nil {
_ = fh.Close()
return fmt.Errorf("error when copying form file %q (%q): %w", k, fv.Filename, err)
}
if err = fh.Close(); err != nil {
return fmt.Errorf("cannot close form file %q (%q): %w", k, fv.Filename, err)
}
}
}
if err := mw.Close(); err != nil {
return fmt.Errorf("error when closing multipart form writer: %w", err)
}
return nil
}
func readMultipartForm(r io.Reader, boundary string, size, maxInMemoryFileSize int) (*multipart.Form, error) {
// Do not care about memory allocations here, since they are tiny
// compared to multipart data (aka multi-MB files) usually sent
// in multipart/form-data requests.
if size <= 0 {
return nil, fmt.Errorf("form size must be greater than 0: given %d", size)
}
lr := io.LimitReader(r, int64(size))
mr := multipart.NewReader(lr, boundary)
f, err := mr.ReadForm(int64(maxInMemoryFileSize))
if err != nil {
return nil, fmt.Errorf("cannot read multipart/form-data body: %w", err)View on GitHub (pinned to c96f600972)
Solutions
- Reset or recreate the Request before retrying (req.Reset()).
- Check the wrapped cause for the writer's underlying failure.
- Validate the multipart form boundary contains only legal boundary characters.
- Upgrade fasthttp if the trigger involves writer reuse after an error.
Example fix
// before
if err := client.Do(req, resp); err != nil {
client.Do(req, resp) // retry on same corrupted req
}
// after
if err := client.Do(req, resp); err != nil {
req.Reset()
req.SetFormFile("f", path)
client.Do(req, resp)
} Defensive patterns
Strategy: try-catch
Validate before calling
if req.MultipartForm != nil && len(req.MultipartFormBoundary) == 0 {
return errors.New("multipart form without boundary set")
} Type guard
func hasValidBoundary(b string) bool {
if len(b) == 0 || len(b) > 70 { return false }
for _, r := range b {
if !isBoundaryChar(r) { return false }
}
return true
} Try / catch
if err := client.Do(req, resp); err != nil {
if strings.Contains(err.Error(), "closing multipart form writer") {
req.Reset()
return rebuildAndRetry()
}
return err
} Prevention
- Let fasthttp generate the boundary instead of hand-setting it
- Reset requests after any failed write before reuse
- Avoid reusing a Request whose previous Do returned mid-write errors
When it happens
Trigger: Finishing marshaling of req.MultipartForm in writeMultipartForm (via client.Do / request writing) when mw.Close() fails — typically after an earlier part write left the underlying buffer/writer in a bad state.
Common situations: Memory/buffer allocation failure in the writer's target; reusing a Request whose multipart writer state is corrupted from a previous aborted write; custom multipartFormBoundary containing invalid characters.
Related errors
- cannot open form file %q (%q): %w
- fasthttp: request content-type has bad boundary or is not mu
- form boundary cannot be empty
- fasthttp: there is no uploaded file associated with the give
- error when copying form file %q (%q): %w
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/a5d719150dcb6f85.
Report an issue: GitHub.