{"record":{"id":"6b6c25e7de5a082b","repo":"github/github-mcp-server","slug":"failed-to-read-response-body-w-6b6c25","errorCode":null,"errorMessage":"failed to read response body: %w","messagePattern":"failed to read response body: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/github/security_advisories.go","lineNumber":197,"sourceCode":"\t\t\t\topts.Published = &published\n\t\t\t}\n\t\t\tif updated != \"\" {\n\t\t\t\topts.Updated = &updated\n\t\t\t}\n\t\t\tif modified != \"\" {\n\t\t\t\topts.Modified = &modified\n\t\t\t}\n\n\t\t\tadvisories, resp, err := client.SecurityAdvisories.ListGlobalSecurityAdvisories(ctx, opts)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to list global security advisories: %w\", err)\n\t\t\t}\n\t\t\tdefer func() { _ = resp.Body.Close() }()\n\n\t\t\tif resp.StatusCode != http.StatusOK {\n\t\t\t\tbody, err := io.ReadAll(resp.Body)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to read response body: %w\", err)\n\t\t\t\t}\n\t\t\t\treturn ghErrors.NewGitHubAPIStatusErrorResponse(ctx, \"failed to list advisories\", resp, body), nil, nil\n\t\t\t}\n\n\t\t\tr, err := json.Marshal(advisories)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"failed to marshal advisories: %w\", err)\n\t\t\t}\n\n\t\t\tresult := utils.NewToolResultText(string(r))\n\t\t\t// Global advisories come from the world-readable GitHub Advisory\n\t\t\t// Database (public) but contain externally authored prose\n\t\t\t// (untrusted).\n\t\t\tresult = attachStaticIFCLabel(ctx, deps, result, ifc.LabelGlobalSecurityAdvisory())\n\t\t\treturn result, nil, nil\n\t\t},\n\t)\n}","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/github/security_advisories.go#L179-L215","documentation":"list_global_security_advisories received a non-200 response and reading that error body failed. The real status - typically 422 bad filter, 403 rate limit, or 5xx - is masked by this secondary transport failure, so the visible message describes only the failed body read.","triggerScenarios":"Non-2xx from ListGlobalSecurityAdvisories followed by a connection break or context cancellation while the error body streamed; deadlines expiring just after headers arrive.","commonSituations":"Marginal networks; hard timeouts in front of the MCP server; rare in stable environments.","solutions":["Retry once - usually transient","If it repeats, review the filter arguments (ecosystem, affects, date ranges) that likely caused the underlying 4xx","Patch the handler to include resp.StatusCode when the body is unreadable"],"exampleFix":"// after\nreturn nil, nil, fmt.Errorf(\"failed to list advisories: status %d (body unreadable: %w)\", resp.StatusCode, err)","handlingStrategy":"retry","validationCode":null,"typeGuard":"func isBodyReadFailure(err error) bool {\n\tvar netErr net.Error\n\treturn errors.As(err, &netErr) || errors.Is(err, io.ErrUnexpectedEOF)\n}","tryCatchPattern":"result, extra, err := callTool(ctx, \"list_global_security_advisories\", args)\nif err != nil && strings.Contains(err.Error(), \"failed to read response body\") {\n    result, extra, err = callTool(ctx, \"list_global_security_advisories\", args)\n}\nif err != nil {\n    return fmt.Errorf(\"advisory listing failed (status masked): %w\", err)\n}","preventionTips":["Set deadlines that cover complete error bodies, not just headers","Retry once on masked-status failures","Review filter arguments when the error recurs - the hidden status is often 422"],"tags":["go","mcp","network","io","security-advisory","http"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}