babalae/better-genshin-impact · error · Exception
下载失败
Error message
下载失败
What it means
Thrown by DownloadRepoAndUnzipCore when the HTTP GET to the repo download URL returns a non-success status code. The response body is not read; only IsSuccessStatusCode is checked. Any 4xx/5xx (or a redirect that HttpClient doesn't follow) triggers this.
Source
Thrown at BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs:2070
{
await _repoWriteLock.WaitAsync();
try
{
await DownloadRepoAndUnzipCore(url);
}
finally
{
_repoWriteLock.Release();
}
}
private async Task DownloadRepoAndUnzipCore(string url)
{
// 下载
var res = await _httpClient.GetAsync(url);
if (!res.IsSuccessStatusCode)
{
throw new Exception("下载失败");
}
var bytes = await res.Content.ReadAsByteArrayAsync();
// 获取文件名
var contentDisposition = res.Content.Headers.ContentDisposition;
var fileName = contentDisposition is { FileName: not null }
? contentDisposition.FileName.Trim('"')
: "temp.zip";
// 创建临时目录
if (!Directory.Exists(ReposTempPath))
{
Directory.CreateDirectory(ReposTempPath);
}
// 保存下载的文件
var zipPath = Path.Combine(ReposTempPath, fileName);View on GitHub (pinned to a7cb36712d)
Solutions
- Include the status code in the error: read res.StatusCode and res.ReasonPhrase before throwing.
- Retry with exponential backoff for transient 5xx/429 responses (the HttpClient has a 30s timeout but no retry).
- Verify the URL in repo.json is reachable: open it in a browser or curl -I.
- For GitHub release assets, ensure the URL is the resolved asset download URL, not the API URL that returns JSON.
Example fix
// before
var res = await _httpClient.GetAsync(url);
if (!res.IsSuccessStatusCode)
throw new Exception("下载失败");
// after (include status + body hint)
var res = await _httpClient.GetAsync(url);
if (!res.IsSuccessStatusCode)
{
var body = await res.Content.ReadAsStringAsync();
throw new HttpRequestException(
$"下载失败: {(int)res.StatusCode} {res.ReasonPhrase}。URL={url}。响应: {body?.Take(200)}");
} Defensive patterns
Strategy: retry
Validate before calling
// Optional pre-check: HEAD the URL
using var probe = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, url));
if (!probe.IsSuccessStatusCode)
throw new HttpRequestException($"下载URL不可用: {(int)probe.StatusCode}"); Try / catch
// Retry transient failures with backoff, then surface the status
int attempt = 0;
HttpResponseMessage res;
do {
res = await _httpClient.GetAsync(url);
if (res.IsSuccessStatusCode) break;
if ((int)res.StatusCode is >= 500 or 429 && attempt < 3)
await Task.Delay(TimeSpan.FromSeconds(1 << attempt));
else break;
} while (++attempt <= 3);
if (!res.IsSuccessStatusCode)
throw new HttpRequestException($"下载失败: {(int)res.StatusCode} {res.ReasonPhrase}"); Prevention
- Always include status code + URL in the error.
- Retry 5xx/429 with exponential backoff.
- Verify repo.json's 'url'/'file' fields point at a live, resolvable asset.
When it happens
Trigger: _httpClient.GetAsync(url) returns a HttpResponseMessage where IsSuccessStatusCode is false — e.g., 404 (wrong URL), 401/403 (auth needed), 5xx (server error), or a timeout surfaced as a status (though HttpClient.Timeout actually throws TaskCanceledException instead).
Common situations: The download URL in repo.json is stale or wrong; the hosting service (e.g., GitHub release assets) moved/removed the file; rate limiting returned 403/429; a proxy returned an error page; the server requires an auth header not configured on the shared HttpClient.
Related errors
- 未找到远程release分支
- 下载的图片内容为空。
- 图片下载超时({DownloadTimeout.TotalSeconds:0} 秒)。
- 下载语言文件失败:{cultureName}.json
- milliseconds 不能小于 0
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/100bf1c09ca75ae9.
Report an issue: GitHub.