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
- Read the body once and reset it: raw, _ := c.GetRawData(); c.Request.Body = io.NopCloser(bytes.NewBuffer(raw)).
- Guard the call: if c.Request != nil && c.Request.Body != nil { ... } before reading.
- 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
- Read the body exactly once per request; reset it if downstream needs it.
- Cache the raw body in c.Set("rawBody", raw) and reuse instead of re-reading.
- Don't call GetRawData for GET requests that never carry a body.
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
- invalid request
- key %v does not exist
- unknown type
- can not convert to map slices of strings
- can not convert to map of strings
AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04).
Data as JSON: /data/errors/44bb3e47cfb2ae7d.json.
Report an issue: GitHub.