{"record":{"id":"06022721dca270c3","repo":"valyala/fasthttp","slug":"form-size-must-be-greater-than-0-given-d","errorCode":null,"errorMessage":"form size must be greater than 0: given %d","messagePattern":"form size must be greater than 0: given (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"http.go","lineNumber":1276,"sourceCode":"\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)\n\t}\n\treturn f, nil\n}\n\n// Reset clears request contents.\nfunc (req *Request) Reset() {\n\treq.userValues.Reset() // it should be at the top, since some values might implement io.Closer interface\n\tif bodyPoolSizeLimit := int(atomic.LoadInt64(&requestBodyPoolSizeLimit)); bodyPoolSizeLimit >= 0 && req.body != nil {\n\t\treq.ReleaseBody(bodyPoolSizeLimit)\n\t}\n\treq.Header.Reset()\n\treq.resetSkipHeader()","sourceCodeStart":1258,"sourceCodeEnd":1294,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/http.go#L1258-L1294","documentation":"fasthttp validates the declared Content-Length (size) before parsing an incoming multipart/form-data body in readMultipartForm; a non-positive size cannot yield any body. This is a server-side guard so it never passes a useless LimitReader to multipart.Reader.","triggerScenarios":"Server request handling (ctx.FormFile / MultipartForm) on a request whose declared multipart size is <= 0 — e.g. Content-Length missing or 0 while a multipart Content-Type is present.","commonSituations":"Clients sending multipart bodies with chunked encoding or no Content-Length; proxies stripping Content-Length; load-generator clients that post empty multipart bodies.","solutions":["Fix the client to send a correct Content-Length with the multipart body.","Server-side: reject requests without a body before calling ctx.FormFile/MultipartForm.","If behind a proxy, configure it to preserve Content-Length for multipart posts.","Send the multipart request via fasthttp's Request (which sets Content-Length automatically) instead of hand-rolled writers."],"exampleFix":"// before (client)\nreq.Header.SetMethod(\"POST\")\nreq.Header.Set(\"Content-Type\", \"multipart/form-data; boundary=x\")\n// body written without length\n// after\nreq.SetFormFileContent(\"file\", data, \"a.txt\") // fasthttp sets CL + boundary\nclient.Do(req, resp)","handlingStrategy":"validation","validationCode":"if ctx.Request.Header.ContentLength() <= 0 {\n    ctx.Error(\"multipart body required\", fasthttp.StatusBadRequest)\n    return\n}","typeGuard":"func hasMultipartBody(ctx *fasthttp.RequestCtx) bool {\n    return ctx.Request.Header.ContentLength() > 0 &&\n        strings.HasPrefix(ctx.Request.Header.ContentType(), \"multipart/form-data\")\n}","tryCatchPattern":"form, err := ctx.MultipartForm()\nif err != nil {\n    if strings.Contains(err.Error(), \"form size must be greater than 0\") {\n        ctx.Error(\"empty multipart body\", fasthttp.StatusBadRequest)\n        return\n    }\n    return err\n}","preventionTips":["Ensure clients send Content-Length with multipart posts","Configure proxies/LBs to preserve Content-Length","Reject zero-length multipart requests at the edge"],"tags":["multipart","content-length","server"],"backgroundTag":"invalid-content-length","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}