{"record":{"id":"053af4714dc58fe9","repo":"gofiber/fiber","slug":"create-file-error-w","errorCode":null,"errorMessage":"create file error: %w","messagePattern":"create file error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/hooks.go","lineNumber":318,"sourceCode":"}\n\nfunc addFormFile(mw *multipart.Writer, f *File, fileBuf *[]byte) error {\n\t// If reader is not set, open the file.\n\tif f.reader == nil {\n\t\tvar err error\n\t\tf.reader, err = os.Open(f.path)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"open file error: %w\", err)\n\t\t}\n\t}\n\n\t// Ensure the file reader is always closed after copying.\n\tdefer f.reader.Close() //nolint:errcheck // not needed\n\n\t// Create form file and copy the content.\n\tw, err := mw.CreateFormFile(f.fieldName, f.name)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create file error: %w\", err)\n\t}\n\n\tif _, err := io.CopyBuffer(w, f.reader, *fileBuf); err != nil {\n\t\treturn fmt.Errorf(\"failed to copy file data: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// parserResponseCookie parses the Set-Cookie headers from the response and stores them.\nfunc parserResponseCookie(c *Client, resp *Response, req *Request) error {\n\tvar err error\n\tfor key, value := range resp.RawResponse.Header.Cookies() {\n\t\tcookie := fasthttp.AcquireCookie()\n\t\tif err = cookie.ParseBytes(value); err != nil {\n\t\t\tfasthttp.ReleaseCookie(cookie)\n\t\t\tbreak\n\t\t}","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/client/hooks.go#L300-L336","documentation":"addFormFile calls mw.CreateFormFile(fieldName, name) to obtain a part writer for the file content. This wraps a failure of that call, which happens when the multipart writer is already closed or the header cannot be constructed (invalid field/file name characters).","triggerScenarios":"fieldName or name contains characters that break the Content-Disposition header (newline, control bytes); mw.Close() was already invoked on this writer; the writer's underlying stream errored.","commonSituations":"User-supplied filenames containing CR/LF (header injection); reusing a multipart writer after close; concurrency on the same writer.","solutions":["Sanitize fieldName and file name — strip CR/LF and other control characters.","Do not call any multipart write method after mw.Close(); let parserRequestBodyFile manage the lifecycle.","Use a deterministic, validated file name rather than raw user input."],"exampleFix":"// before\nf.SetName(userSuppliedName)\n\n// after\nsafe := strings.Map(func(r rune) rune {\n    if r < 0x20 || r == 0x7f { return -1 }\n    return r\n}, userSuppliedName)\nf.SetName(safe)","handlingStrategy":"validation","validationCode":"func safeMultipartName(s string) string {\n    return strings.Map(func(r rune) rune {\n        if r < 0x20 || r == 0x7f { return -1 }\n        return r\n    }, s)\n}\nf.SetName(safeMultipartName(name))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Sanitize field and file names to remove CR/LF and control bytes (header-injection defense).","Never reuse a multipart writer after Close.","Avoid concurrent writes to the same multipart writer."],"tags":["client","multipart","header-injection","file-upload"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}