{"record":{"id":"a5d719150dcb6f85","repo":"valyala/fasthttp","slug":"error-when-closing-multipart-form-writer-w","errorCode":null,"errorMessage":"error when closing multipart form writer: %w","messagePattern":"error when closing multipart form writer: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"http.go","lineNumber":1264,"sourceCode":"\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"cannot create form file %q (%q): %w\", k, fv.Filename, err)\n\t\t\t}\n\t\t\tfh, err := fv.Open()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"cannot open form file %q (%q): %w\", k, fv.Filename, err)\n\t\t\t}\n\t\t\tif _, err = copyZeroAlloc(vw, fh); err != nil {\n\t\t\t\t_ = fh.Close()\n\t\t\t\treturn fmt.Errorf(\"error when copying form file %q (%q): %w\", k, fv.Filename, err)\n\t\t\t}\n\t\t\tif err = fh.Close(); err != nil {\n\t\t\t\treturn fmt.Errorf(\"cannot close form file %q (%q): %w\", k, fv.Filename, err)\n\t\t\t}\n\t\t}\n\t}\n\n\tif err := mw.Close(); err != nil {\n\t\treturn fmt.Errorf(\"error when closing multipart form writer: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc readMultipartForm(r io.Reader, boundary string, size, maxInMemoryFileSize int) (*multipart.Form, error) {\n\t// Do not care about memory allocations here, since they are tiny\n\t// compared to multipart data (aka multi-MB files) usually sent\n\t// in multipart/form-data requests.\n\n\tif size <= 0 {\n\t\treturn nil, fmt.Errorf(\"form size must be greater than 0: given %d\", size)\n\t}\n\tlr := io.LimitReader(r, int64(size))\n\tmr := multipart.NewReader(lr, boundary)\n\tf, err := mr.ReadForm(int64(maxInMemoryFileSize))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot read multipart/form-data body: %w\", err)","sourceCodeStart":1246,"sourceCodeEnd":1282,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/http.go#L1246-L1282","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif err := client.Do(req, resp); err != nil {\n    client.Do(req, resp) // retry on same corrupted req\n}\n// after\nif err := client.Do(req, resp); err != nil {\n    req.Reset()\n    req.SetFormFile(\"f\", path)\n    client.Do(req, resp)\n}","handlingStrategy":"try-catch","validationCode":"if req.MultipartForm != nil && len(req.MultipartFormBoundary) == 0 {\n    return errors.New(\"multipart form without boundary set\")\n}","typeGuard":"func hasValidBoundary(b string) bool {\n    if len(b) == 0 || len(b) > 70 { return false }\n    for _, r := range b {\n        if !isBoundaryChar(r) { return false }\n    }\n    return true\n}","tryCatchPattern":"if err := client.Do(req, resp); err != nil {\n    if strings.Contains(err.Error(), \"closing multipart form writer\") {\n        req.Reset()\n        return rebuildAndRetry()\n    }\n    return err\n}","preventionTips":["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"],"tags":["multipart","form-data","writer"],"backgroundTag":"multipart-form-write-failed","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}