NickeManarin/ScreenToGif · warning · WebException

Empty response from server when getting language codes

Error message

Empty response from server when getting language codes

What it means

A WebException thrown inside GetLanguageCodesAsync after the second HTTP request (to the resolved language-codes path) succeeds with an HttpWebResponse but response.GetResponseStream() returns null. The guard fires before reading the stream, treating a null stream as an unrecoverable 'empty response from server'. In practice GetResponseStream rarely returns null for a valid HttpWebResponse, so this path is an edge case for broken proxies/streaming transports.

Source

Thrown at ScreenToGif/Windows/Other/Localization.xaml.cs:416

    }

    private async Task<IEnumerable<string>> GetLanguageCodesAsync()
    {
        var path = await GetLanguageCodesPathAsync();

        if (string.IsNullOrEmpty(path))
            throw new WebException("Can't get language codes. Path to language codes is null");

        var request = (HttpWebRequest)WebRequest.Create(path);
        request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393";
        request.Proxy = WebHelper.GetProxy();

        var response = (HttpWebResponse)await request.GetResponseAsync();

        using (var resultStream = response.GetResponseStream())
        {
            if (resultStream == null)
                throw new WebException("Empty response from server when getting language codes");

            using (var reader = new StreamReader(resultStream))
            {
                var result = await reader.ReadToEndAsync();

                var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(result),
                    new System.Xml.XmlDictionaryReaderQuotas());

                var json = await Task<XElement>.Factory.StartNew(() => XElement.Load(jsonReader));
                var languages = json.Elements();

                return await Task.Factory.StartNew(() => languages.Where(x => x.XPathSelectElement("defs")?.Value != "0").Select(x => x.XPathSelectElement("lang")?.Value));
            }
        }
    }

    private async Task<string> GetLanguageCodesPathAsync()
    {

View on GitHub (pinned to a4d0a67c21)

Solutions

  1. Check HTTP status code before reading: if ((int)response.StatusCode >= 400) handle the error rather than assuming a body exists.
  2. Retry the request once — null streams are typically transient transport/proxy issues.
  3. Inspect WebHelper.GetProxy() configuration; a misconfigured proxy can strip bodies.
  4. Verify the resolved language-codes path URL (from GetLanguageCodesPathAsync) is reachable and returns JSON in a browser/curl.
  5. Fall back to the bundled hardcoded language code list (the GetSomething fallback near line 380) when the network path fails.

Example fix

// before
var response = (HttpWebResponse)await request.GetResponseAsync();
using (var resultStream = response.GetResponseStream())
{
    if (resultStream == null)
        throw new WebException("Empty response from server when getting language codes");

// after: check status + null-safe read with fallback
var response = (HttpWebResponse)await request.GetResponseAsync();
using (var resultStream = response.GetResponseStream())
{
    if (resultStream == null || response.ContentLength == 0)
    {
        LogWriter.Log($"Empty language-codes body. Status: {response.StatusCode}, URL: {path}");
        return Enumerable.Empty<string>(); // caller falls back to bundled list
    }
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check connectivity and the resolved URL before requesting the codes.
if (string.IsNullOrEmpty(path) || !Uri.IsWellFormedUriString(path, UriKind.Absolute))
    throw new InvalidOperationException("Language codes path is not a valid URL.");

if (!NetworkHelper.IsOnline())
    throw new WebException("No network connectivity to fetch language codes.");

Type guard

static bool HasReadableBody(HttpWebResponse response) =>
    response != null && (int)response.StatusCode < 400 && response.ContentLength != 0;

var response = (HttpWebResponse)await request.GetResponseAsync();
if (!HasReadableBody(response))
    return Enumerable.Empty<string>(); // let caller use bundled fallback

Try / catch

// Retry once on a null/empty stream, then degrade to the bundled list.
IEnumerable<string> result = null;
for (var attempt = 0; attempt < 2 && result == null; attempt++)
{
    try { result = await GetLanguageCodesAsync(); }
    catch (WebException wex) when (wex.Message.Contains("Empty response from server when getting language codes"))
    {
        LogWriter.Log(wex, $"Null language-codes stream on attempt {attempt + 1}.");
        if (attempt == 1) return GetBundledLanguageCodes();
        await Task.Delay(500);
    }
}
return result;

Prevention

When it happens

Trigger: GetResponseAsync() returned a non-null HttpWebResponse (no throw), but GetResponseStream() evaluated to null. This can happen with a malformed chunked-encoding response, a transparent proxy that closed the body, a 2xx with Content-Length 0 that some implementations surface as a null stream, or a custom WebRequest descendant returning null.

Common situations: A corporate/transparent proxy stripping the response body; the datahub.io CDN returned an empty 200 with no body; a transient TLS/connection close where the response headers arrived but the body stream could not be constructed; custom proxy via WebHelper.GetProxy misbehaving.

Related errors


AI-assisted analysis of NickeManarin/ScreenToGif@a4d0a67c21 (2026-08-13). Data as JSON: /api/errors/37c9e2dde0bb2712. Report an issue: GitHub.