github/github-mcp-server · error

failed to fetch raw content: %s

Error message

failed to fetch raw content: %s

What it means

The raw content endpoint for a repo:// resource returned a status other than 200 or 404, and this error embeds the raw response body verbatim via %s. Typical bodies are GitHub's error documents: 401 'Bad credentials' (expired/revoked token), 403 rate limit or blocked repo, or 5xx from the raw CDN. The message omits the HTTP status code, so the cause must be inferred from the body text.

Source

Thrown at pkg/github/repository_resource.go:254

				}

				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...),
	}

	switch {
	case sha != "":

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Read the embedded body: 'Bad credentials' means rotate/refresh the token; 'rate limit' means back off and respect Retry-After
  2. Verify the token against raw content directly: curl -H "Authorization: Bearer $TOKEN" https://raw.githubusercontent.com/owner/repo/main/README.md
  3. For 403 secondary rate limits, wait and retry with exponential backoff
  4. Improve the handler to prefix resp.Status so triage does not depend on parsing the body

Example fix

// before
return nil, fmt.Errorf("failed to fetch raw content: %s", string(body))
// after - keep the status code and trim the body
return nil, fmt.Errorf("failed to fetch raw content: %s: %s", resp.Status, bytes.TrimSpace(body))
Defensive patterns

Strategy: try-catch

Validate before calling

// Fail fast before bulk raw reads: verify the token and rate-limit headroom
rl, resp, err := client.RateLimit.Get(ctx)
if err != nil || resp.StatusCode != http.StatusOK {
    return fmt.Errorf("token or API unusable, aborting raw reads: %v", err)
}
if rl.GetCore().Remaining == 0 {
    return fmt.Errorf("rate limit exhausted until %v", rl.GetCore().Reset.Time)
}

Type guard

func classifyRawContentError(msg string) string {
	switch {
	case strings.Contains(msg, "Bad credentials"):
		return "invalid-token"
	case strings.Contains(msg, "rate limit"), strings.Contains(msg, "secondary rate limit"):
		return "rate-limited"
	case strings.Contains(msg, "404"):
		return "not-found"
	default:
		return "unknown"
	}
}

Try / catch

result, err := readResource(ctx, uri)
if err != nil && strings.HasPrefix(err.Error(), "failed to fetch raw content") {
    switch classifyRawContentError(err.Error()) {
    case "invalid-token":
        return errors.New("raw content token expired or revoked; refresh it")
    case "rate-limited":
        time.Sleep(time.Until(resetAt)) // then retry
    default:
        return err
    }
}

Prevention

When it happens

Trigger: Expired or revoked PAT on raw.githubusercontent.com; secondary rate limit (403 'You have exceeded a secondary rate limit') from aggressive raw fetches; private repo the token cannot read; 5xx incident on the raw CDN; wrong raw host for GH_HOST/GHE configurations.

Common situations: Long-running servers whose token expired mid-session; CI jobs fetching many raw files and tripping abuse detection; misconfigured GH_HOST so raw requests go to a host that rejects them.

Related errors


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