gin-gonic/gin · error

cannot read nil body

Error message

cannot read nil body

What it means

Returned by Context.GetRawData (context.go:1146) when c.Request.Body is nil. GetRawData calls io.ReadAll on the request body, which would NPE on a nil reader, so Gin guards it. A nil body is normal for GET/HEAD/DELETE without a body and after the body has already been consumed.

Source

Thrown at context.go:1146

// It writes a header in the response.
// If value == "", this method removes the header `c.Writer.Header().Del(key)`
func (c *Context) Header(key, value string) {
	if value == "" {
		c.Writer.Header().Del(key)
		return
	}
	c.Writer.Header().Set(key, value)
}

// GetHeader returns value from request headers.
func (c *Context) GetHeader(key string) string {
	return c.requestHeader(key)
}

// GetRawData returns stream data.
func (c *Context) GetRawData() ([]byte, error) {
	if c.Request.Body == nil {
		return nil, errors.New("cannot read nil body")
	}
	return io.ReadAll(c.Request.Body)
}

// SetSameSite with cookie
func (c *Context) SetSameSite(samesite http.SameSite) {
	c.sameSite = samesite
}

// SetCookie adds a Set-Cookie header to the ResponseWriter's headers.
// The provided cookie must have a valid Name. Invalid cookies may be
// silently dropped.
func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) {
	if path == "" {
		path = "/"
	}
	http.SetCookie(c.Writer, &http.Cookie{
		Name:     name,

View on GitHub (pinned to 34dac209ff)

Solutions

  1. Read the body once and reset it: raw, _ := c.GetRawData(); c.Request.Body = io.NopCloser(bytes.NewBuffer(raw)).
  2. Guard the call: if c.Request != nil && c.Request.Body != nil { ... } before reading.
  3. Use c.ShouldBindJSON / c.GetRawData in only one place per request lifecycle.

Example fix

// before
raw, _ := c.GetRawData() // in logger
// later in handler
raw2, _ := c.GetRawData() // Body is nil -> error
// after
raw, _ := c.GetRawData()
c.Request.Body = io.NopCloser(bytes.NewBuffer(raw)) // restore for downstream readers
Defensive patterns

Strategy: validation

Validate before calling

if c.Request == nil || c.Request.Body == nil {
    return nil, errors.New("no body to read")
}
return c.GetRawData()

Try / catch

raw, err := c.GetRawData()
if err != nil {
    if err.Error() == "cannot read nil body" {
        // body already consumed or absent; reset from a cached copy if you saved one
    }
}

Prevention

When it happens

Trigger: Calling c.GetRawData() on a GET request (no body); calling it twice — the first call drains and closes Body, the second sees nil; middleware that consumed the body without resetting it.

Common situations: Logging middleware that reads the body, then a handler also calls GetRawData; reading the body for signature verification then trying to read it again; using GetRawData instead of c.ShouldBindJSON for JSON payloads.

Related errors


AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04). Data as JSON: /data/errors/44bb3e47cfb2ae7d.json. Report an issue: GitHub.