{"record":{"id":"a91503ba049a627e","repo":"bytebase/bytebase","slug":"failed-to-read-body","errorCode":null,"errorMessage":"failed to read body","messagePattern":"failed to read body","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/idp/oidc/oidc.go","lineNumber":282,"sourceCode":"\tclient := &http.Client{\n\t\t// Reached before authentication through GetAuthenticationInfo, which the\n\t\t// dashboard awaits before it mounts, so a blackholing issuer must not\n\t\t// hold a page load open for long.\n\t\tTimeout: 3 * time.Second,\n\t\tTransport: &http.Transport{\n\t\t\tTLSClientConfig: &tls.Config{\n\t\t\t\tInsecureSkipVerify: insecureSkipVerify,\n\t\t\t},\n\t\t},\n\t}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"fetch openid configuration\")\n\t}\n\n\tb, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to read body\")\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, errors.Errorf(\"received non-200 response code, code: %d, body: %s\", resp.StatusCode, string(b))\n\t}\n\n\tvar config OpenIDConfigurationResponse\n\tif err := json.Unmarshal(b, &config); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"unmarshal openid configuration, body: %s\", string(b))\n\t}\n\treturn &config, nil\n}\n","sourceCodeStart":264,"sourceCodeEnd":296,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/idp/oidc/oidc.go#L264-L296","documentation":"fetchOpenIDConfiguration downloads the OIDC provider's discovery document (.well-known/openid-configuration). This error is thrown when io.ReadAll fails while draining the response body, typically because the connection was reset or timed out mid-transfer. It wraps the underlying I/O error so the root cause is preserved in the message chain.","triggerScenarios":"Calling fetchOpenIDConfiguration when the HTTP server closes the connection or the connection drops while streaming the discovery document body, e.g. resp.Body read interrupted after headers were received.","commonSituations":"Provider behind a load balancer with aggressive idle timeouts; TLS termination proxy cutting the response short; network blips between the Bytebase server and the identity provider; provider sending Content-Length larger than what it sends before closing.","solutions":["Retry the fetch — transient connection resets usually resolve on a second attempt.","Check network connectivity and any proxy/firewall between Bytebase and the OIDC provider's issuer URL.","Inspect the wrapped root-cause error for timeouts and increase the HTTP client timeout if it is too small.","Verify the provider endpoint is healthy by fetching the discovery URL with curl."],"exampleFix":"// before\nb, err := io.ReadAll(resp.Body)\nif err != nil {\n    return nil, errors.Wrapf(err, \"failed to read body\")\n}\n// after\nb, err := io.ReadAll(io.LimitReader(resp.Body, maxConfigSize))\nif err != nil {\n    return nil, errors.Wrapf(err, \"failed to read body from %s\", discoveryURL)\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"if err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) && netErr.Timeout() {\n        // backoff and retry the fetch\n    }\n    return fmt.Errorf(\"oidc discovery fetch failed: %w\", err)\n}","preventionTips":["Set a sane HTTP client timeout on the OIDC fetch client","Retry transient body-read failures with exponential backoff","Monitor provider endpoint health; alert on repeated mid-body disconnects"],"tags":["network","http","oidc"],"backgroundTag":"network-request-failed","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}