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

  1. Reset the request before reuse: req.Reset() (or use AcquireRequest/ReleaseRequest pairs) so stale bodies are cleared.
  2. Only set the body when the method permits it, or call req.SetBodyRaw(nil) / Remove the body when the method is not POST.
  3. 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

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


AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31). Data as JSON: /api/errors/f2f9acc98946fe27. Report an issue: GitHub.