github/github-mcp-server · warning

failed to read response body: %w

Error message

failed to read response body: %w

What it means

Returned by getProject when the GitHub REST API answers a non-200 status (e.g. 404, 403) and reading the response body for the error payload itself fails with io.ReadAll. The double failure (API error + unreadable body) prevents building the structured GitHubAPIStatusErrorResponse. Typically indicates the connection was torn down mid-response, a proxy truncated the body, or the body was already consumed.

Source

Thrown at pkg/github/projects.go:1348

	}
	return !project.GetPublic(), nil
}

func getProject(ctx context.Context, client *github.Client, owner, ownerType string, projectNumber int) (*mcp.CallToolResult, bool, any, error) {
	project, resp, err := fetchProjectV2(ctx, client, owner, ownerType, projectNumber)
	if err != nil {
		return ghErrors.NewGitHubAPIErrorResponse(ctx,
			"failed to get project",
			resp,
			err,
		), false, nil, nil
	}
	defer func() { _ = resp.Body.Close() }()

	if resp.StatusCode != http.StatusOK {
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			return nil, false, nil, fmt.Errorf("failed to read response body: %w", err)
		}
		return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get project", resp, body), false, nil, nil
	}

	minimalProject := convertToMinimalProject(project)
	r, err := json.Marshal(minimalProject)
	if err != nil {
		return nil, false, nil, fmt.Errorf("failed to marshal response: %w", err)
	}

	return utils.NewToolResultText(string(r)), !project.GetPublic(), nil, nil
}

func getProjectField(ctx context.Context, client *github.Client, owner, ownerType string, projectNumber int, fieldID int64) (*mcp.CallToolResult, any, error) {
	var resp *github.Response
	var projectField *github.ProjectV2Field
	var err error

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Retry the tool call once — transient transport truncation usually clears
  2. Check network stability between the server and api.github.com (or GHES host): proxies, MTU, idle timeouts
  3. If a custom http.Client/Transport wraps requests, ensure it does not consume and close resp.Body before the handler reads it
  4. Capture transport-level logs (GITHUB_TOKEN ok? proxy env set?) when it recurs, and report with the status code you saw
Defensive patterns

Strategy: retry

Validate before calling

// nothing to validate client-side; you can pre-check connectivity/egress health before long crawls
func egressHealthy(ctx context.Context, host string) error {
    c := http.Client{Timeout: 5 * time.Second}
    r, err := c.Head("https://" + host)
    if err != nil {
        return err
    }
    _ = r.Body.Close()
    return nil
}

Try / catch

res, isPrivate, r, err := getProject(ctx, client, owner, ownerType, number)
if err != nil {
    if strings.Contains(err.Error(), "failed to read response body") {
        // transient transport truncation: safe to retry once with backoff
        time.Sleep(500 * time.Millisecond)
        res, isPrivate, r, err = getProject(ctx, client, owner, ownerType, number)
    }
    if err != nil {
        return err
    }
}

Prevention

When it happens

Trigger: GitHub or an intermediate proxy closes the connection before the error body is fully transmitted (race with rate-limit resets or LB idle timeouts); TLS interruption mid-body; a transport retry that already drained resp.Body; extremely large error payloads hitting reader limits.

Common situations: Flaky corporate networks and TLS-terminating proxies; GHES instances behind aggressive load balancers; running under constrained CI egress where responses are truncated; retry wrappers that consume bodies.

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/0b24bf8db15d9f8e. Report an issue: GitHub.