valyala/fasthttp · error

non-zero body for non-post request: body=%q

Error message

non-zero body for non-post request: body=%q

What it means

fasthttp refuses to write a request that has a non-empty body but is not a method that normally carries one (i.e. not POST and not flagged as having a body, such as via SetBytesBody on allowed methods or Request.SetHost style overrides). With secureErrorLogMessage the body is omitted from the message; otherwise the body content is quoted.

Source

Thrown at http.go:1867

	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.
//
// Level is the desired compression level:
//

View on GitHub (pinned to c96f600972)

Solutions

  1. Set req.Header.SetMethod(fasthttp.MethodPost) (or PUT) when a body is intended.
  2. Clear the body with req.ResetBody() when the method must remain GET/HEAD.
  3. Check helper functions that set both method and body; only use the body-setting ones for POST/PUT.
  4. If the server expects a body on GET, send POST instead or use a client that permits it explicitly.

Example fix

// before
req.SetBodyString(payload)
req.Header.SetMethod(fasthttp.MethodGet)
// after
req.Header.SetMethod(fasthttp.MethodPost)
req.SetBodyString(payload)
Defensive patterns

Strategy: validation

Validate before calling

if req.Header.Method() != fasthttp.MethodPost && req.Header.Method() != fasthttp.MethodPut && len(req.Body()) > 0 {
    return errors.New("body set on non-post request")
}

Type guard

func bodyAllowed(method []byte) bool {
    switch string(method) {
    case "POST", "PUT", "PATCH":
        return true
    }
    return false
}

Try / catch

if err := client.Do(req, resp); err != nil {
    if strings.Contains(err.Error(), "non-zero body for non-post request") {
        req.ResetBody()
        req.Header.SetMethod(fasthttp.MethodPost)
        return client.Do(req, resp)
    }
    return err
}

Prevention

When it happens

Trigger: Setting a body (SetBody/SetBodyString/SetFormFileContent without proper method) then issuing GET/HEAD/DELETE etc.; doRequest path builds the request with hasBody false but len(body) > 0.

Common situations: Copy-pasting POST code and changing only the method to GET while keeping the body; switching a client helper to HEAD for health checks while still setting a payload; middleware that clears the method but not the body.

Related errors


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