{"record":{"id":"fd9b61a6587423ae","repo":"gofiber/fiber","slug":"failed-to-close-multipart-writer-w","errorCode":null,"errorMessage":"failed to close multipart writer: %w","messagePattern":"failed to close multipart writer: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/hooks.go","lineNumber":250,"sourceCode":"\treturn nil\n}\n\n// parserRequestBodyFile handles the case where the request contains files to be uploaded.\nfunc parserRequestBodyFile(req *Request) error {\n\tmw := multipart.NewWriter(req.RawRequest.BodyWriter())\n\tif err := mw.SetBoundary(req.boundary); err != nil {\n\t\treturn fmt.Errorf(\"set boundary error: %w\", err)\n\t}\n\n\tif err := writeMultipartBody(mw, req); err != nil {\n\t\tmw.Close() //nolint:errcheck // the body write already failed; surface that error instead\n\t\treturn err\n\t}\n\n\t// Close writes the trailing boundary; if it fails the multipart body is\n\t// incomplete, so surface the error instead of sending a malformed request.\n\tif err := mw.Close(); err != nil {\n\t\treturn fmt.Errorf(\"failed to close multipart writer: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// writeMultipartBody writes the form fields and files of req to mw.\nfunc writeMultipartBody(mw *multipart.Writer, req *Request) error {\n\t// Add form data.\n\tvar err error\n\tfor key, value := range req.formData.All() {\n\t\terr = mw.WriteField(utils.UnsafeString(key), utils.UnsafeString(value))\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"write formdata error: %w\", err)\n\t}","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/client/hooks.go#L232-L268","documentation":"After all form fields and files are written, parserRequestBodyFile calls mw.Close() to emit the trailing multipart boundary. This wraps a failure of that Close, meaning the underlying body writer reported an error finalizing the multipart payload, so the request body would be malformed if sent.","triggerScenarios":"The request's BodyWriter (a bytes.Buffer or pipe backing the raw request) returns an error on the final write; an injected streaming body writer that fails; memory exhaustion while buffering a very large upload.","commonSituations":"A custom BodyWriter (e.g. an http.Pipe) whose write side errored; content-length/size mismatch in a streaming upload; the connection or underlying buffer was closed early by another goroutine.","solutions":["Check the wrapped cause — it identifies whether the buffer, pipe, or streaming writer failed.","Avoid mutating or closing the request's RawRequest concurrently with sending.","If streaming a large upload, ensure the body writer's lifecycle outlives mw.Close()."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := c.Post(url, req); err != nil {\n    if strings.Contains(err.Error(), \"failed to close multipart writer\") {\n        // body writer failed finalizing multipart; do not retry the same body\n    }\n}","preventionTips":["Do not close or mutate the request's RawRequest body concurrently with the send.","Keep the BodyWriter alive until the request completes.","For streaming bodies, ensure the producer outlives mw.Close()."],"tags":["client","multipart","body-writer","upload","io"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}