CoplayDev/unity-mcp · error · InvalidOperationException
GitHub request failed: {(int)response.StatusCode} {response.
Error message
GitHub request failed: {(int)response.StatusCode} {response.ReasonPhrase} ({url})\n{body} What it means
DownloadString throws when any GitHub REST API call (branches or git/trees) returns a non-success status. The message embeds the numeric status code, reason phrase, the requested URL, and the response body for diagnosis.
Source
Thrown at MCPForUnity/Editor/Setup/SkillSyncService.cs:297
internal static HttpClient CreateGitHubClient()
{
var client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(60)
};
client.DefaultRequestHeaders.UserAgent.ParseAdd("UnityMcpSkillSync/1.0");
client.DefaultRequestHeaders.Accept.ParseAdd("application/vnd.github+json");
return client;
}
internal static string DownloadString(HttpClient client, string url)
{
using var response = client.GetAsync(url).GetAwaiter().GetResult();
var body = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
if (!response.IsSuccessStatusCode)
{
throw new InvalidOperationException($"GitHub request failed: {(int)response.StatusCode} {response.ReasonPhrase} ({url})\n{body}");
}
return body;
}
private static byte[] DownloadBytes(HttpClient client, string url)
{
using var response = client.GetAsync(url).GetAwaiter().GetResult();
if (!response.IsSuccessStatusCode)
{
var body = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
throw new InvalidOperationException($"File download failed: {(int)response.StatusCode} {response.ReasonPhrase} ({url})\n{body}");
}
return response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
}
internal static string NormalizeRemotePath(string path)View on GitHub (pinned to c21bf496bc)
Solutions
- Read the status code in the message: 403 => rate limit, 404 => wrong identifier, 401 => private repo.
- For 403: wait for the rate-limit reset window (check X-RateLimit headers) before retrying.
- For 404: verify owner, repo, and branch spellings.
- For private repos: the service has no token support, so sync from a public mirror/fork.
Defensive patterns
Strategy: retry
Try / catch
try
{
var json = SkillSyncService.DownloadString(client, url);
}
catch (InvalidOperationException ex)
{
if (ex.Message.Contains("403"))
log?.Invoke("GitHub rate limit hit. Wait for the reset window before retrying.");
else if (ex.Message.Contains("404"))
log?.Invoke("GitHub returned 404. Check owner/repo/branch spelling.");
throw;
} Prevention
- Throttle sync frequency to stay under the unauthenticated rate limit.
- Verify owner/repo/branch spellings before syncing.
- Use a public repo or mirror; the service sends no auth token for private repos.
When it happens
Trigger: 403 Forbidden from unauthenticated rate limiting (~60 req/hr per IP); 404 Not Found for a wrong owner/repo/branch/tree; 401 if a private repo is targeted; 5xx during a GitHub outage.
Common situations: Repeated syncs exhausting the unauthenticated rate limit; typo in owner/repo; targeting a private repo (the service sends no auth token); GitHub incident.
Related errors
- fal {phase} failed (status={res?.Status}): {detail}
- fal {phase} failed (status={res?.Status}): {detail}
- Failed to parse GitHub directory tree response.
- GitHub returned a truncated directory tree (incomplete snaps
- Failed to resolve branch head commit SHA for: {branch}
AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13).
Data as JSON: /api/errors/7e1ccab1f1fb4e53.
Report an issue: GitHub.