{"record":{"id":"6aa06f5a8ac99c61","repo":"NickeManarin/ScreenToGif","slug":"can-t-get-language-codes-path-to-language-codes-i-6aa06f","errorCode":null,"errorMessage":"Can't get language codes. Path to language codes is null","messagePattern":"Can't get language codes\\. Path to language codes is null","errorType":"exception","errorClass":"WebException","httpStatus":null,"severity":"warning","filePath":"ScreenToGif/Windows/Other/Localization.xaml.cs","lineNumber":405,"sourceCode":"                \"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;\" +\n                \"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;\" +\n                \"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;\" +\n                \"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;\" +\n                \"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;\" +\n                \"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;\" +\n                \"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;\" +\n                \"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;\" +\n                \"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;\" +\n                \"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;\" +\n                \"yo-BJ;zgh;zh;zh-Hans-HK;zh-Hans-MO;zh-Hant;zu\").Split(';').ToList();\n    }\n\n    private async Task<IEnumerable<string>> GetLanguageCodesAsync()\n    {\n        var path = await GetLanguageCodesPathAsync();\n\n        if (string.IsNullOrEmpty(path))\n            throw new WebException(\"Can't get language codes. Path to language codes is null\");\n\n        var request = (HttpWebRequest)WebRequest.Create(path);\n        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\";\n        request.Proxy = WebHelper.GetProxy();\n\n        var response = (HttpWebResponse)await request.GetResponseAsync();\n\n        using (var resultStream = response.GetResponseStream())\n        {\n            if (resultStream == null)\n                throw new WebException(\"Empty response from server when getting language codes\");\n\n            using (var reader = new StreamReader(resultStream))\n            {\n                var result = await reader.ReadToEndAsync();\n\n                var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(result),\n                    new System.Xml.XmlDictionaryReaderQuotas());","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/NickeManarin/ScreenToGif/blob/a4d0a67c2131cd048ceec86cd40afc2f1a06f2fd/ScreenToGif/Windows/Other/Localization.xaml.cs#L387-L423","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["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.","If the schema changed, update the XPath selector in GetLanguageCodesPathAsync to match the new resource name/field.","Provide a hardcoded fallback URL for the language-codes JSON so a null path does not break localization download.","Check network connectivity / proxy (WebHelper.GetProxy) and retry, since a proxied truncated response can yield malformed JSON that parses to a missing resource.","Cache the last known good path so transient upstream changes don't break the feature."],"exampleFix":"// before\nvar path = await GetLanguageCodesPathAsync();\nif (string.IsNullOrEmpty(path))\n    throw new WebException(\"Can't get language codes. Path to language codes is null\");\n\n// after: fall back to a known-good direct URL instead of throwing\nvar path = await GetLanguageCodesPathAsync();\nif (string.IsNullOrEmpty(path))\n{\n    LogWriter.Log(\"Language codes path lookup returned null; using fallback URL.\");\n    path = \"https://raw.githubusercontent.com/datasets/language-codes/master/data/ietf-language-tags.json\";\n}","handlingStrategy":"fallback","validationCode":"// Pre-check the upstream datapackage shape before relying on the path.\nvar probe = await GetLanguageCodesPathAsync();\nif (string.IsNullOrEmpty(probe))\n{\n    // Use a known-good direct URL; don't let the second request build a null URL.\n    probe = \"https://pkgstore.datahub.io/core/language-codes/ietf-language-tags_json/data/ietf-language-tags.json\";\n}","typeGuard":"static bool HasLanguageCodesPath(string path) =>\n    !string.IsNullOrWhiteSpace(path) && Uri.IsWellFormedUriString(path, UriKind.Absolute);\n\nif (!HasLanguageCodesPath(path))\n    path = /* fallback URL */;","tryCatchPattern":"try\n{\n    var codes = await GetLanguageCodesAsync();\n}\ncatch (WebException wex) when (wex.Message.Contains(\"Path to language codes is null\"))\n{\n    LogWriter.Log(wex, \"Upstream datapackage.json schema changed; using fallback URL.\");\n    // Re-run against a hardcoded fallback URL.\n}\ncatch (InvalidOperationException iex)\n{\n    // First(...) inside GetLanguageCodesPathAsync threw — resource renamed.\n    LogWriter.Log(iex, \"ietf-language-tags_json resource not found in datapackage.json.\");\n}","preventionTips":["Cache the last-good language-codes path so an upstream rename doesn't break the feature.","Pin a versioned/direct URL instead of resolving through datapackage.json at runtime.","Add an integration test that asserts the datapackage.json still contains the expected resource name.","Ship a bundled fallback language-code list so offline/upstream failures degrade gracefully."],"tags":["network","webexception","json","xpath","localization","datahub","upstream-dependency"],"backgroundTag":null,"analyzedSha":"a4d0a67c2131cd048ceec86cd40afc2f1a06f2fd","analyzedAt":"2026-08-13T11:12:06.147Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}