{"id":"44bb3e47cfb2ae7d","repo":"gin-gonic/gin","slug":"cannot-read-nil-body","errorCode":null,"errorMessage":"cannot read nil body","messagePattern":"cannot read nil body","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"context.go","lineNumber":1146,"sourceCode":"// It writes a header in the response.\n// If value == \"\", this method removes the header `c.Writer.Header().Del(key)`\nfunc (c *Context) Header(key, value string) {\n\tif value == \"\" {\n\t\tc.Writer.Header().Del(key)\n\t\treturn\n\t}\n\tc.Writer.Header().Set(key, value)\n}\n\n// GetHeader returns value from request headers.\nfunc (c *Context) GetHeader(key string) string {\n\treturn c.requestHeader(key)\n}\n\n// GetRawData returns stream data.\nfunc (c *Context) GetRawData() ([]byte, error) {\n\tif c.Request.Body == nil {\n\t\treturn nil, errors.New(\"cannot read nil body\")\n\t}\n\treturn io.ReadAll(c.Request.Body)\n}\n\n// SetSameSite with cookie\nfunc (c *Context) SetSameSite(samesite http.SameSite) {\n\tc.sameSite = samesite\n}\n\n// SetCookie adds a Set-Cookie header to the ResponseWriter's headers.\n// The provided cookie must have a valid Name. Invalid cookies may be\n// silently dropped.\nfunc (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) {\n\tif path == \"\" {\n\t\tpath = \"/\"\n\t}\n\thttp.SetCookie(c.Writer, &http.Cookie{\n\t\tName:     name,","sourceCodeStart":1128,"sourceCodeEnd":1164,"githubUrl":"https://github.com/gin-gonic/gin/blob/34dac209ffb6ef85cc78c5d217bbb7ad001d68fd/context.go#L1128-L1164","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nraw, _ := c.GetRawData() // in logger\n// later in handler\nraw2, _ := c.GetRawData() // Body is nil -> error\n// after\nraw, _ := c.GetRawData()\nc.Request.Body = io.NopCloser(bytes.NewBuffer(raw)) // restore for downstream readers","handlingStrategy":"validation","validationCode":"if c.Request == nil || c.Request.Body == nil {\n    return nil, errors.New(\"no body to read\")\n}\nreturn c.GetRawData()","typeGuard":null,"tryCatchPattern":"raw, err := c.GetRawData()\nif err != nil {\n    if err.Error() == \"cannot read nil body\" {\n        // body already consumed or absent; reset from a cached copy if you saved one\n    }\n}","preventionTips":["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."],"tags":["request","body","middleware","go"],"analyzedSha":"34dac209ffb6ef85cc78c5d217bbb7ad001d68fd","analyzedAt":"2026-08-04T21:26:18.438Z","schemaVersion":2}