Flow-Launcher/Flow.Launcher · error · HttpRequestException

Error code <{response.StatusCode}> with content <{content}>

Error message

Error code <{response.StatusCode}> with content <{content}> returned from <{url}>

What it means

Thrown as HttpRequestException from GetAsync(Uri) when response.StatusCode != HttpStatusCode.OK. Unlike DownloadAsync, the full response body is read first and embedded in the message, so the exception text includes both the status code, the URL, and the raw content — useful for diagnosing API errors that return JSON error payloads with a non-200 status.

Source

Thrown at Flow.Launcher.Infrastructure/Http/Http.cs:166

        {
            Log.Debug(ClassName, $"Url <{url}>");
            return GetAsync(new Uri(url), token);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="url"></param>
        /// <param name="token"></param>
        /// <returns>The Http result as string. Null if cancellation requested</returns>
        public static async Task<string> GetAsync([NotNull] Uri url, CancellationToken token = default)
        {
            Log.Debug(ClassName, $"Url <{url}>");
            using var response = await client.GetAsync(url, token);
            var content = await response.Content.ReadAsStringAsync(token);
            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new HttpRequestException(
                    $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>");
            }

            return content;
        }

        /// <summary>
        /// Send a GET request to the specified Uri with an HTTP completion option and a cancellation token as an asynchronous operation.
        /// </summary>
        /// <param name="url">The Uri the request is sent to.</param>
        /// <param name="completionOption">An HTTP completion option value that indicates when the operation should be considered completed.</param>
        /// <param name="token">A cancellation token that can be used by other objects or threads to receive notice of cancellation</param>
        /// <returns></returns>
        public static Task<Stream> GetStreamAsync([NotNull] string url,
            CancellationToken token = default) => GetStreamAsync(new Uri(url), token);

        /// <summary>
        /// Send a GET request to the specified Uri with an HTTP completion option and a cancellation token as an asynchronous operation.

View on GitHub (pinned to 7fc63b07bb)

Solutions

  1. Read the embedded content in the exception message — it usually contains the server's error description.
  2. Confirm the URL is current and the endpoint accepts unauthenticated GET.
  3. For 429, implement exponential backoff and respect Retry-After.
  4. For 401/403, supply the required header/token via the request.
  5. If the server legitimately returns non-OK with a usable body, change the check from '!= OK' to 'IsSuccessStatusCode' to accept all 2xx.

Example fix

// before — rejects any non-200, even other 2xx
if (response.StatusCode != HttpStatusCode.OK)
    throw new HttpRequestException(...);

// after — accept all 2xx success codes
if (!response.IsSuccessStatusCode)
    throw new HttpRequestException(
        $"{(int)response.StatusCode} from <{url}>: {content}");
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try { return await Http.GetAsync(url, token); }
catch (HttpRequestException ex) { Log.Exception(ClassName, $"GET {url} failed: {ex.Message}", ex); throw; }

Prevention

When it happens

Trigger: Calling GetAsync against a plugin-update/manifest endpoint that returns 404, 401, 500; an API gateway returns 200-shaped JSON with a 4xx status; the server returns 304 Not Modified (which != OK) when a conditional header is present; any 3xx redirect that HttpClient didn't auto-follow (e.g. to a disallowed scheme).

Common situations: Plugin marketplace/update API returning an error payload; user behind a proxy that injects a 407; expired auth token producing 401; rate-limited APIs returning 429; server-side validation errors returning 400 with a JSON body.

Related errors


AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13). Data as JSON: /api/errors/a180a36853491d96. Report an issue: GitHub.