Flow-Launcher/Flow.Launcher · error · HttpRequestException
Error code <{response.StatusCode}> returned from <{url}>
Error message
Error code <{response.StatusCode}> returned from <{url}> What it means
Thrown as HttpRequestException inside DownloadAsync when the HTTP response status code is not a success (response.IsSuccessStatusCode is false) while attempting to download a file to disk. It is caught by the local catch which logs 'Http Request Error' and rethrows, so callers see the exception. Unlike GetAsync, the response body is NOT captured — only the status code and URL are in the message.
Source
Thrown at Flow.Launcher.Infrastructure/Http/Http.cs:131
if (token.IsCancellationRequested)
return;
else
reportProgress(progressValue);
}
if (progressValue < 100)
reportProgress(100);
}
else
{
await using var fileStream = new FileStream(filePath, FileMode.CreateNew);
await response.Content.CopyToAsync(fileStream, token);
}
}
else
{
throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>");
}
}
catch (HttpRequestException e)
{
Log.Exception(ClassName, "Http Request Error", e, "DownloadAsync");
throw;
}
}
/// <summary>
/// Asynchrously get the result as string from url.
/// When supposing the result larger than 83kb, try using GetStreamAsync to avoid reading as string
/// </summary>
/// <param name="url"></param>
/// <returns>The Http result as string. Null if cancellation requested</returns>
public static Task<string> GetAsync([NotNull] string url, CancellationToken token = default)
{
Log.Debug(ClassName, $"Url <{url}>");View on GitHub (pinned to 7fc63b07bb)
Solutions
- Open the URL in a browser to see the actual status/body — the message gives you the code and endpoint.
- Check whether the download host is up and the path still exists (common for GitHub release assets that were re-published).
- Retry with backoff for transient 5xx/429 codes.
- If behind a proxy, ensure HttpClient.DefaultProxy / system proxy is configured correctly.
- For 403/401, verify the URL doesn't require authentication or an accept header.
Example fix
// before
if (!response.IsSuccessStatusCode)
throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>");
// after — include body and retry on transient codes
if (!response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync(token);
throw new HttpRequestException(
$"{(int)response.StatusCode} {response.StatusCode} from <{url}>: {body}");
} Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
int attempt = 0;
retry:
try { await Http.DownloadAsync(url, filePath, token); }
catch (HttpRequestException ex) when ((int)ex.StatusCode >= 500 && ++attempt < 3)
{ await Task.Delay(TimeSpan.FromSeconds(1 << attempt), token); goto retry; } Prevention
- Verify the download URL returns 200 in a browser before relying on it.
- Implement retry with backoff for transient 5xx/429 responses.
- Configure the system proxy / HttpClient.DefaultProxy in corporate environments.
- Log the status code to distinguish missing (404) from server (5xx) failures.
When it happens
Trigger: Plugin/metadata download URL returns 404 (file removed), 403 (hotlinking blocked), 500/503 (server error), 401 (auth required); the update server is behind a CDN that rate-limits with a 429; a redirect chain ends in an error code because HttpClient doesn't follow cross-scheme or certain redirect types.
Common situations: Plugin author moved or deleted the release asset but didn't update the manifest URL; corporate proxy returns 407/502; GitHub rate limiting on raw.githubusercontent or release downloads; the host is offline and a captive portal returns 200/302 to a login page (note: 200 wouldn't throw, but a portal returning 4xx would).
Related errors
- Error code <{response.StatusCode}> with content <{content}>
- Plugin {newPlugin.ID} zip file not found at {filePath}
AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13).
Data as JSON: /api/errors/3677e53941c7bd52.
Report an issue: GitHub.