{"record":{"id":"3175e736ae3a1853","repo":"hashicorp/nomad","slug":"error-decoding-stats-data-stats-were-nil","errorCode":null,"errorMessage":"error decoding stats data: stats were nil","messagePattern":"error decoding stats data: stats were nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/docker/stats.go","lineNumber":156,"sourceCode":"\t})\n\tif err != nil && err != io.EOF {\n\t\treturn nil, fmt.Errorf(\"failed to collect stats: %w\", err)\n\t}\n\n\t// Ensure the body is not nil to avoid potential panics. The statsReader\n\t// itself cannot be nil, so there is no need to check this.\n\tif statsReader.Body == nil {\n\t\treturn nil, errors.New(\"error decoding stats data: no reader body\")\n\t}\n\n\terr = json.NewDecoder(statsReader.Body).Decode(&stats)\n\t_ = statsReader.Body.Close()\n\tif err != nil && err != io.EOF {\n\t\treturn nil, fmt.Errorf(\"failed to decode Docker response: %w\", err)\n\t}\n\n\tif stats == nil {\n\t\treturn nil, errors.New(\"error decoding stats data: stats were nil\")\n\t}\n\n\treturn stats, nil\n}\n","sourceCodeStart":138,"sourceCodeEnd":161,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/docker/stats.go#L138-L161","documentation":"After successfully decoding the Docker stats API response into a DockerStats struct, collectDockerStats checks that the result is non-nil. A nil decoded value means the daemon returned an empty/JSON-null payload, so the driver reports this error rather than propagating a useless nil stats object.","triggerScenarios":"Docker's stats endpoint returns a null/empty JSON body (decode succeeds, err is nil or io.EOF) and the resulting stats struct is nil during collectStats.","commonSituations":"Container stopped/removed between request and decode; Docker daemon returning `{}`/null on transient failures; odd pre-1.x daemon behaviors during host memory pressure.","solutions":["Confirm the container is still running; handle stop/remove races before stats collection","Retry the collection — transient daemon responses usually resolve","Upgrade/restart the Docker daemon if null stats responses persist"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// verify container is running before decoding stats\ninfo, err := cli.ContainerInspect(ctx, containerID)\nif err != nil || !info.State.Running { return fmt.Errorf(\"container not running\") }","typeGuard":"func statsDecoded(s *DockerStats) bool { return s != nil }","tryCatchPattern":"stats, err := collectDockerStats(ctx, cli, containerID)\nif err != nil {\n    if strings.Contains(err.Error(), \"stats were nil\") {\n        return retryWithBackoff(3, func() (interface{}, error) { return collectDockerStats(ctx, cli, containerID) })\n    }\n    return nil, err\n}","preventionTips":["Handle container stop/remove races before stats collection","Add retries around Docker stats polling","Report persistent null stats payloads to the Docker daemon maintainers"],"tags":["nomad","docker","stats","json-decode"],"backgroundTag":"empty-response-body","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}