{"record":{"id":"c14df82b406531f8","repo":"Netflix/chaosmonkey","slug":"body-read-failed-at-s","errorCode":null,"errorMessage":"body read failed at %s","messagePattern":"body read failed at (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"spinnaker/config.go","lineNumber":48,"sourceCode":"\tresp, err := s.client.Get(url)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"http get failed at %s\", url)\n\t}\n\n\tdefer func() {\n\t\tif cerr := resp.Body.Close(); cerr != nil && err == nil {\n\t\t\terr = errors.Wrapf(err, \"body close failed at %s\", url)\n\t\t}\n\t}()\n\n\t// should return a 200\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, errors.Errorf(\"unexpected response code (%d) from %s\", resp.StatusCode, url)\n\t}\n\n\tbody, err := ioutil.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"body read failed at %s\", url)\n\t}\n\n\treturn fromJSON(body)\n}\n","sourceCodeStart":30,"sourceCodeEnd":53,"githubUrl":"https://github.com/Netflix/chaosmonkey/blob/eaa28fb761c0ebe8644d1333e5d164e9cc3071e9/spinnaker/config.go#L30-L53","documentation":"Once a 200 response is received, Get reads the entire response body with ioutil.ReadAll. A read failure (connection reset mid-body, premature close, chunked encoding error) is wrapped as 'body read failed at <url>'.","triggerScenarios":"ioutil.ReadAll(resp.Body) errors: connection dropped while streaming the body, proxy/gateway terminating the response early, TLS errors mid-transfer, or body already closed by intermediate handling.","commonSituations":"Large app configs over flaky networks; proxies/load balancers with short idle timeouts cutting the response; Spinnaker gate crash mid-response; aggressive keep-alive timeouts.","solutions":["Retry the Get request — transient body truncation usually succeeds on retry","Check proxy/load balancer timeout settings between the monkey and the gate","Inspect the wrapped cause for whether the connection was reset or timed out","Consider a client with sane timeouts and retry policy for the gate client"],"exampleFix":"// caller-side retry guard\nvar cfg *chaosmonkey.AppConfig\nvar err error\nfor i := 0; i < 3; i++ {\n    cfg, err = getter.Get(app)\n    if err == nil || !strings.Contains(fmt.Sprintf(\"%v\", err), \"body read failed\") {\n        break\n    }\n    time.Sleep(time.Duration(1<<i) * time.Second)\n}","handlingStrategy":"retry","validationCode":"// check content-length/type hints before reading fully\nct := resp.Header.Get(\"Content-Type\")\nif !strings.HasPrefix(ct, \"application/json\") {\n    return fmt.Errorf(\"expected JSON, got %s\", ct)\n}","typeGuard":null,"tryCatchPattern":"cfg, err := getter.Get(app)\nif err != nil && strings.Contains(err.Error(), \"body read failed\") {\n    time.Sleep(2 * time.Second)\n    cfg, err = getter.Get(app) // transient truncations usually clear on retry\n}","preventionTips":["Increase proxy/load balancer response timeouts for the gate route","Set reasonable client timeouts so partial reads fail fast and retry cleanly","Monitor for connection resets between the monkey and the gate","Avoid extremely large responses by keeping Spinnaker app configs lean"],"tags":["go","http","spinnaker","io"],"backgroundTag":"response-body-read-failed","analyzedSha":"eaa28fb761c0ebe8644d1333e5d164e9cc3071e9","analyzedAt":"2026-09-03T17:04:39.020Z","contentChangedAt":"2026-09-03T17:04:39.020Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}