github/github-mcp-server · error
failed to read response body: %w
Error message
failed to read response body: %w
What it means
In the repo:// resource handler, the raw content request came back with a status other than 200 or 404, and io.ReadAll of that error response body failed. The real API failure (rate limit, auth, 5xx) is masked by this secondary transport error: the message describes the failed body read, not the underlying status, which is lost entirely.
Source
Thrown at pkg/github/repository_resource.go:252
if err := base64Encoder.Close(); err != nil {
return nil, fmt.Errorf("failed to close base64 encoder: %w", err)
}
return &mcp.ReadResourceResult{
Contents: []*mcp.ResourceContents{
{
URI: request.Params.URI,
MIMEType: mimeType,
Blob: buf.Bytes(),
},
},
}, nil
}
case resp.StatusCode != http.StatusNotFound:
// If we got a response but it is not 200 OK, we return an error
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
return nil, fmt.Errorf("failed to fetch raw content: %s", string(body))
default:
// This should be unreachable because GetContents should return an error if neither file nor directory content is found.
return nil, errors.New("404 Not Found")
}
}
}
// expandRepoResourceURI builds a resource URI using the appropriate URI template
// based on the provided parameters (sha, ref, or default).
func expandRepoResourceURI(owner, repo, sha, ref string, pathParts []string) (string, error) {
baseValues := uritemplate.Values{
"owner": uritemplate.String(owner),
"repo": uritemplate.String(repo),
"path": uritemplate.List(pathParts...),
}
View on GitHub (pinned to 0ea1f775a7)
Solutions
- Retry the resource read - the masked status was likely transient (429/5xx) and the body-read failure is a network blip
- If it repeats, patch the handler to include resp.StatusCode in the error so the real status is never lost
- Verify token validity and rate-limit state when the pattern recurs on every call
Example fix
// before
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
return nil, fmt.Errorf("failed to fetch raw content: %s", string(body))
// after - never lose the status code
return nil, fmt.Errorf("failed to fetch raw content: status %d (body unreadable: %w)", resp.StatusCode, err) Defensive patterns
Strategy: retry
Type guard
func isBodyReadFailure(err error) bool {
var netErr net.Error
return errors.As(err, &netErr) || errors.Is(err, io.ErrUnexpectedEOF)
} Try / catch
err := readResource(ctx, uri)
if err != nil {
if isBodyReadFailure(err) {
// secondary transport failure masked the real HTTP status; retry
time.Sleep(300 * time.Millisecond)
err = readResource(ctx, uri)
}
if err != nil {
return fmt.Errorf("repo resource read failed (status masked by body read error): %w", err)
}
} Prevention
- Give the MCP server request contexts deadlines longer than worst-case response latency
- Monitor for this message pattern - it indicates the network is dropping responses mid-body
- Patch the handler locally to surface resp.StatusCode when the body read fails
When it happens
Trigger: GetRawContent returns 403/429/5xx and the connection breaks or the context deadline expires while streaming even the small error body; client timeouts set so tight the error body cannot be fully read.
Common situations: Flaky networks where resets hit right after headers; servers under load where GitHub sends 5xx slowly; hard per-request timeouts in front of the MCP server.
Related errors
- failed to read file content: %w
- failed to read response body: %w
- failed to read response body: %w
- failed to read response body: %w
- failed to fetch raw content: %s
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/bb3e36deb99677a3.
Report an issue: GitHub.