{"record":{"id":"371de7cfc0669021","repo":"thanos-io/thanos","slug":"failed-to-read-body","errorCode":null,"errorMessage":"failed to read body","messagePattern":"failed to read body","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/promclient/promclient.go","lineNumber":312,"sourceCode":"\tu.Path = path.Join(u.Path, \"/api/v1/status/flags\")\n\n\treq, err := http.NewRequest(http.MethodGet, u.String(), nil)\n\tif err != nil {\n\t\treturn Flags{}, errors.Wrap(err, \"create request\")\n\t}\n\n\tspan, ctx := tracing.StartSpan(ctx, \"/prom_flags HTTP[client]\")\n\tdefer span.Finish()\n\n\tresp, err := c.Do(req.WithContext(ctx))\n\tif err != nil {\n\t\treturn Flags{}, errors.Wrapf(err, \"request config against %s\", u.String())\n\t}\n\tdefer runutil.ExhaustCloseWithLogOnErr(c.logger, resp.Body, \"query body\")\n\n\tb, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn Flags{}, errors.New(\"failed to read body\")\n\t}\n\n\tswitch resp.StatusCode {\n\tcase 404:\n\t\treturn Flags{}, ErrFlagEndpointNotFound\n\tcase 200:\n\t\tvar d struct {\n\t\t\tData Flags `json:\"data\"`\n\t\t}\n\n\t\tif err := json.Unmarshal(b, &d); err != nil {\n\t\t\treturn Flags{}, errors.Wrapf(err, \"unmarshal response: %v\", string(b))\n\t\t}\n\n\t\treturn d.Data, nil\n\tdefault:\n\t\treturn Flags{}, errors.Errorf(\"got non-200 response code: %v, response: %v\", resp.StatusCode, string(b))\n\t}","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/promclient/promclient.go#L294-L330","documentation":"ConfiguredFlags reads the response body with io.ReadAll; if reading fails (connection reset mid-body, truncated response, context cancellation during body read), a plain 'failed to read body' error is returned. Unlike the wrapped request error, this one does not include the underlying cause text beyond the sentinel message.","triggerScenarios":"io.ReadAll(resp.Body) errors after a successful HTTP response — server closed the connection prematurely, network interruption during body transfer, or the request context was canceled mid-read. Called by an anonymous caller fetching Prometheus flags.","commonSituations":"Flaky network between Thanos and Prometheus; load balancer idle timeouts cutting the response; Prometheus restarting while serving the request; proxy buffering limits truncating large flag payloads.","solutions":["Retry the request — this is typically transient network interruption","Check logs on the Prometheus/proxy side for connection resets","Increase or check proxy/load-balancer idle timeouts","Ensure the context isn't canceled prematurely (deadline too tight)"],"exampleFix":"// before: single attempt\nflags, err := client.ConfiguredFlags(ctx, base)\n// after: retry transient read failures\nvar flags promclient.Flags\nerr := retry.Do(func() error {\n    var e error\n    flags, e = client.ConfiguredFlags(ctx, base)\n    return e\n}, retry.Attempts(3), retry.RetryIf(func(err error) bool {\n    return strings.Contains(err.Error(), \"failed to read body\")\n}))","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"var flags promclient.Flags\nerr := backoff.Retry(func() error {\n    var err error\n    flags, err = client.ConfiguredFlags(ctx, u)\n    if err != nil && strings.Contains(err.Error(), \"failed to read body\") {\n        return backoff.Permanent(err) // or retry, depending on policy\n    }\n    return err\n}, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 3))","preventionTips":["Retry idempotent GET requests on body-read failures","Raise LB/proxy idle timeouts above client timeouts","Avoid tight context deadlines for flag/config fetches","Monitor Prometheus restarts that correlate with these errors"],"tags":["network","http","body-read","transient"],"backgroundTag":"file-read-failed","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}