{"record":{"id":"f2f9acc98946fe27","repo":"valyala/fasthttp","slug":"non-zero-body-for-non-post-request","errorCode":null,"errorMessage":"non-zero body for non-post request","messagePattern":"non-zero body for non-post request","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"http.go","lineNumber":1865,"sourceCode":"\t\treq.Header.SetMultipartFormBoundary(req.multipartFormBoundary)\n\t}\n\n\thasBody := false\n\tif len(body) == 0 {\n\t\tbody = req.postArgs.QueryString()\n\t}\n\tif len(body) != 0 || !req.Header.ignoreBody() {\n\t\thasBody = true\n\t\treq.Header.SetContentLength(len(body))\n\t}\n\tif err = req.Header.Write(w); err != nil {\n\t\treturn err\n\t}\n\tif hasBody {\n\t\t_, err = w.Write(body)\n\t} else if len(body) > 0 {\n\t\tif req.secureErrorLogMessage {\n\t\t\treturn errors.New(\"non-zero body for non-post request\")\n\t\t}\n\t\treturn fmt.Errorf(\"non-zero body for non-post request: body=%q\", body)\n\t}\n\treturn err\n}\n\n// WriteGzip writes response with gzipped body to w.\n//\n// The method gzips response body and sets 'Content-Encoding: gzip'\n// header before writing response to w.\n//\n// WriteGzip doesn't flush response to w for performance reasons.\nfunc (resp *Response) WriteGzip(w *bufio.Writer) error {\n\treturn resp.WriteGzipLevel(w, CompressDefaultCompression)\n}\n\n// WriteGzipLevel writes response with gzipped body to w.\n//","sourceCodeStart":1847,"sourceCodeEnd":1883,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/http.go#L1847-L1883","documentation":"When writing an HTTP request, fasthttp only allows a request body on methods that can carry one (e.g. POST). If a non-POST request has leftover body bytes, it refuses to send them; with secureErrorLogMessage enabled the error is generic, otherwise it includes the offending body contents.","triggerScenarios":"Acquiring a Request from the pool, using it previously as a POST with a body, then reusing it for GET without resetting; explicitly setting a body on a GET/HEAD/DELETE request and calling WriteTo or client.Do.","commonSituations":"Request-pool reuse where Reset/refresh of headers skipped the body; code that sets req.SetBody* unconditionally regardless of method; switching a request's method from POST to GET but keeping the old payload.","solutions":["Reset the request before reuse: req.Reset() (or use AcquireRequest/ReleaseRequest pairs) so stale bodies are cleared.","Only set the body when the method permits it, or call req.SetBodyRaw(nil) / Remove the body when the method is not POST.","If the body is intentional, keep the method as POST (or another body-allowing method)."],"exampleFix":"// before\nreq.Reset() // headers reset but body retained from previous POST\nreq.Header.SetMethod(\"GET\")\nclient.Do(req, resp) // non-zero body for non-post request\n// after\nreq.Reset()\nreq.Header.SetMethod(\"GET\")\nreq.SetBodyRaw(nil) // ensure no body for GET\nclient.Do(req, resp)","handlingStrategy":"validation","validationCode":"func cleanForMethod(req *fasthttp.Request) {\n    switch string(req.Header.Method()) {\n    case \"GET\", \"HEAD\", \"OPTIONS\", \"DELETE\":\n        req.SetBodyRaw(nil)\n    }\n}","typeGuard":null,"tryCatchPattern":"err := client.Do(req, resp)\nif err != nil && strings.HasPrefix(err.Error(), \"non-zero body for non-post request\") {\n    req.SetBodyRaw(nil)\n    err = client.Do(req, resp)\n}","preventionTips":["Always call req.Reset() when reusing pooled requests.","Set the body only after finalizing the method.","Never release/acquire requests across different call sites without reset."],"tags":["http","request-body","request-reuse"],"backgroundTag":"get-request-with-body","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}