valyala/fasthttp · error
non-zero body for non-post request
Error message
non-zero body for non-post request
What it means
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.
Source
Thrown at http.go:1865
req.Header.SetMultipartFormBoundary(req.multipartFormBoundary)
}
hasBody := false
if len(body) == 0 {
body = req.postArgs.QueryString()
}
if len(body) != 0 || !req.Header.ignoreBody() {
hasBody = true
req.Header.SetContentLength(len(body))
}
if err = req.Header.Write(w); err != nil {
return err
}
if hasBody {
_, err = w.Write(body)
} else if len(body) > 0 {
if req.secureErrorLogMessage {
return errors.New("non-zero body for non-post request")
}
return fmt.Errorf("non-zero body for non-post request: body=%q", body)
}
return err
}
// WriteGzip writes response with gzipped body to w.
//
// The method gzips response body and sets 'Content-Encoding: gzip'
// header before writing response to w.
//
// WriteGzip doesn't flush response to w for performance reasons.
func (resp *Response) WriteGzip(w *bufio.Writer) error {
return resp.WriteGzipLevel(w, CompressDefaultCompression)
}
// WriteGzipLevel writes response with gzipped body to w.
//View on GitHub (pinned to c96f600972)
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).
Example fix
// before
req.Reset() // headers reset but body retained from previous POST
req.Header.SetMethod("GET")
client.Do(req, resp) // non-zero body for non-post request
// after
req.Reset()
req.Header.SetMethod("GET")
req.SetBodyRaw(nil) // ensure no body for GET
client.Do(req, resp) Defensive patterns
Strategy: validation
Validate before calling
func cleanForMethod(req *fasthttp.Request) {
switch string(req.Header.Method()) {
case "GET", "HEAD", "OPTIONS", "DELETE":
req.SetBodyRaw(nil)
}
} Try / catch
err := client.Do(req, resp)
if err != nil && strings.HasPrefix(err.Error(), "non-zero body for non-post request") {
req.SetBodyRaw(nil)
err = client.Do(req, resp)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- fasthttp: cannot follow a body-preserving redirect for a req
- too large hex number
- fasthttp: missing location header for http redirect
- fasthttp: too many redirects detected when doing the request
- fasthttp: hostclient can't follow redirects to a different p
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/f2f9acc98946fe27.
Report an issue: GitHub.