NickeManarin/ScreenToGif · warning · WebException

Can't get language codes. Path to language codes is null

Error message

Can't get language codes. Path to language codes is null

What it means

A WebException thrown by GetLanguageCodesAsync when GetLanguageCodesPathAsync() returned an empty/null string. GetLanguageCodesPathAsync parses the datahub.io datapackage.json and extracts the 'path' of the ietf-language-tags_json resource via XPath; if the JSON shape changed, the resource was renamed/removed, or the XPath chain short-circuited on a null element, the returned path is null and this guard rejects it before building the second HttpWebRequest.

Source

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

                "en-NL;en-NR;en-NU;en-NZ;en-PG;en-PH;en-PK;en-PN;en-PW;en-RW;en-SB;en-SC;en-SD;en-SE;en-SG;en-SH;en-SI;en-SL;en-SS;en-SX;en-SZ;en-TK;en-TO;en-TT;en-TV;" +
                "en-TZ;en-UG;en-VC;en-VU;en-WS;en-ZA;en-ZM;en-ZW;eo;es;es-419;es-AR;es-BO;es-BR;es-BZ;es-CL;es-CO;es-CR;es-CU;es-DO;es-EC;es-GQ;es-GT;es-HN;es-MX;es-NI;" +
                "es-PA;es-PE;es-PH;es-PR;es-PY;es-SV;es-US;es-UY;es-VE;et;eu;ewo;fa;ff;ff-Latn-GH;ff-Latn-GM;ff-Latn-GN;ff-Latn-LR;ff-Latn-MR;ff-Latn-NG;ff-Latn-SL;fi;fil;" +
                "fo;fo-DK;fr;fr-BE;fr-BI;fr-CA;fr-CD;fr-CH;fr-CI;fr-CM;fr-DJ;fr-DZ;fr-GF;fr-GN;fr-HT;fr-KM;fr-LU;fr-MA;fr-MG;fr-ML;fr-MR;fr-MU;fr-RE;fr-RW;fr-SC;fr-SN;fr-SY;" +
                "fr-TD;fr-TN;fr-VU;fur;fy;ga;gd;gl;gsw;gu;guz;gv;ha;haw;he;hi;hr;hr-BA;hsb;hu;hy;ia;id;ig;ii;is;it;it-CH;ja;jgo;jmc;jv;ka;kab;kam;kde;kea;khq;ki;kk;kkj;kl;kln;" +
                "km;kn;ko;ko-KP;kok;ks;ksb;ksf;ksh;ku;kw;ky;lag;lb;lg;lkt;ln;ln-AO;lo;lrc;lrc-IQ;lt;lu;luo;luy;lv;mas;mas-TZ;mer;mfe;mg;mgh;mgo;mi;mk;ml;mn;mni;mr;ms;ms-BN;ms-SG;" +
                "mt;mua;my;mzn;naq;nb;nd;nds;nds-NL;ne;ne-IN;nl;nl-AW;nl-BE;nl-BQ;nl-CW;nl-SR;nl-SX;nmg;nn;nnh;nus;nyn;om;om-KE;or;os;os-RU;pa;pa-Arab;pl;prg;ps;ps-PK;pt;pt-AO;" +
                "pt-CV;pt-GW;pt-LU;pt-MO;pt-MZ;pt-PT;pt-ST;pt-TL;rm;rn;ro;ro-MD;rof;ru;ru-BY;ru-KG;ru-KZ;ru-MD;ru-UA;rw;rwk;sah;saq;sbp;sd;sd-Deva;se;se-FI;se-SE;seh;ses;sg;shi;" +
                "shi-Latn;si;sk;sl;smn;sn;so;so-DJ;so-ET;so-KE;sq;sq-MK;sq-XK;sr;sr-Cyrl-BA;sr-Cyrl-ME;sr-Cyrl-XK;sr-Latn;sr-Latn-BA;sr-Latn-ME;sr-Latn-XK;sv;sv-FI;sw;sw-CD;sw-KE;" +
                "sw-UG;ta;ta-LK;ta-MY;ta-SG;te;teo;teo-KE;tg;th;ti;ti-ER;tk;to;tr;tr-CY;tt;twq;tzm;ug;uk;ur;ur-IN;uz;uz-Arab;uz-Cyrl;vai;vai-Latn;vi;vo;vun;wae;wo;xh;xog;yav;yi;yo;" +
                "yo-BJ;zgh;zh;zh-Hans-HK;zh-Hans-MO;zh-Hant;zu").Split(';').ToList();
    }

    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());

View on GitHub (pinned to a4d0a67c21)

Solutions

  1. Verify the datahub.io endpoint (https://datahub.io/core/language-codes/datapackage.json) still contains a resource named 'ietf-language-tags_json' with a 'path' field — open it in a browser.
  2. If the schema changed, update the XPath selector in GetLanguageCodesPathAsync to match the new resource name/field.
  3. Provide a hardcoded fallback URL for the language-codes JSON so a null path does not break localization download.
  4. Check network connectivity / proxy (WebHelper.GetProxy) and retry, since a proxied truncated response can yield malformed JSON that parses to a missing resource.
  5. Cache the last known good path so transient upstream changes don't break the feature.

Example fix

// before
var path = await GetLanguageCodesPathAsync();
if (string.IsNullOrEmpty(path))
    throw new WebException("Can't get language codes. Path to language codes is null");

// after: fall back to a known-good direct URL instead of throwing
var path = await GetLanguageCodesPathAsync();
if (string.IsNullOrEmpty(path))
{
    LogWriter.Log("Language codes path lookup returned null; using fallback URL.");
    path = "https://raw.githubusercontent.com/datasets/language-codes/master/data/ietf-language-tags.json";
}
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-check the upstream datapackage shape before relying on the path.
var probe = await GetLanguageCodesPathAsync();
if (string.IsNullOrEmpty(probe))
{
    // Use a known-good direct URL; don't let the second request build a null URL.
    probe = "https://pkgstore.datahub.io/core/language-codes/ietf-language-tags_json/data/ietf-language-tags.json";
}

Type guard

static bool HasLanguageCodesPath(string path) =>
    !string.IsNullOrWhiteSpace(path) && Uri.IsWellFormedUriString(path, UriKind.Absolute);

if (!HasLanguageCodesPath(path))
    path = /* fallback URL */;

Try / catch

try
{
    var codes = await GetLanguageCodesAsync();
}
catch (WebException wex) when (wex.Message.Contains("Path to language codes is null"))
{
    LogWriter.Log(wex, "Upstream datapackage.json schema changed; using fallback URL.");
    // Re-run against a hardcoded fallback URL.
}
catch (InvalidOperationException iex)
{
    // First(...) inside GetLanguageCodesPathAsync threw — resource renamed.
    LogWriter.Log(iex, "ietf-language-tags_json resource not found in datapackage.json.");
}

Prevention

When it happens

Trigger: GetLanguageCodesPathAsync returns null/empty. This occurs when the downloaded datapackage.json no longer contains a resource named 'ietf-language-tags_json', when the 'path' element is absent, or when the resources element itself is missing (XPathSelectElement('resources')?.Elements() yields nothing, so First(...) would actually throw InvalidOperationException — but a null 'path' value short-circuits to null via the trailing ?.Value).

Common situations: The upstream datahub.io dataset schema changed (resource renamed/restructured); the response was truncated by a proxy/cache returning partial JSON; a network filter rewrote the response; running offline and a stale/empty cached body was used; the datahub.io endpoint moved or deprecated language-codes/core.

Related errors


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