{"record":{"id":"b751a8dc8ca9ac5a","repo":"JosefNemec/Playnite","slug":"failed-to-download-string-from-all-mirrors","errorCode":null,"errorMessage":"Failed to download string from all mirrors.","messagePattern":"Failed to download string from all mirrors\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"source/Playnite/Common/Web/Downloader.cs","lineNumber":79,"sourceCode":"        {\r\n        }\r\n\r\n        public string DownloadString(IEnumerable<string> mirrors)\r\n        {\r\n            logger.Debug($\"Downloading string content from multiple mirrors.\");\r\n            foreach (var mirror in mirrors)\r\n            {\r\n                try\r\n                {\r\n                    return DownloadString(mirror);\r\n                }\r\n                catch (Exception e)\r\n                {\r\n                    logger.Error(e, $\"Failed to download {mirror} string.\");\r\n                }\r\n            }\r\n\r\n            throw new Exception(\"Failed to download string from all mirrors.\");\r\n        }\r\n\r\n        public string DownloadString(string url)\r\n        {\r\n            return DownloadString(url, Encoding.UTF8);\r\n        }\r\n\r\n        public string DownloadString(string url, CancellationToken cancelToken)\r\n        {\r\n            logger.Debug($\"Downloading string content from {url} using UTF8 encoding.\");\r\n\r\n            try\r\n            {\r\n                using (var webClient = new CustomWebClient { Encoding = Encoding.UTF8 })\r\n                using (var registration = cancelToken.Register(() => webClient.CancelAsync()))\r\n                {\r\n                    webClient.Headers.Add(\"User-Agent\", playniteUserAgent);\r\n                    return Task.Run(async () => await webClient.DownloadStringTaskAsync(url)).GetAwaiter().GetResult();\r","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/JosefNemec/Playnite/blob/5911f4e964e628aa7a69c2030ab35101afa63067/source/Playnite/Common/Web/Downloader.cs#L61-L97","documentation":"Thrown by Downloader.DownloadString(IEnumerable<string> mirrors) when every mirror URL in the list raised an exception (each mirror's DownloadString attempt is caught and logged). It is a bare Exception with no inner exception aggregating the per-mirror failures.","triggerScenarios":"All mirrors are unreachable (offline, DNS failure, 4xx/5xx, TLS error, timeout); mirrors list is empty so the loop body never runs and it throws immediately; network proxy blocking all hosts.","commonSituations":"Fetching update/metadata strings during an outage or behind a captive portal; mirror URLs misconfigured; corporate firewall/proxy rejecting the hosts; expired TLS cert on all mirrors.","solutions":["Check connectivity and that at least one mirror URL is reachable in a browser.","Review the logged per-mirror errors (logger.Error above the throw) for the real cause.","Verify the mirrors list is non-empty and the URLs are correct.","Configure the proxy/cert chain or retry when the network recovers."],"exampleFix":"// before\nvar s = downloader.DownloadString(mirrors);\n\n// after — guard empty list and capture per-mirror failures\nif (mirrors == null || !mirrors.Any()) throw new InvalidOperationException(\"No mirrors configured.\");\nList<Exception> failures = new List<Exception>();\nforeach (var m in mirrors)\n{\n    try { return downloader.DownloadString(m); }\n    catch (Exception e) { failures.Add(e); }\n}\nthrow new AggregateException(\"All mirrors failed\", failures);","handlingStrategy":"retry","validationCode":"if (mirrors == null || !mirrors.Any()) throw new InvalidOperationException(\"No mirrors configured.\");","typeGuard":"static bool HasMirrors(IEnumerable<string> m) => m != null && m.Any(s => !s.IsNullOrWhiteSpace());","tryCatchPattern":"try { return downloader.DownloadString(mirrors); }\ncatch (Exception ex) { logger.Error(ex, \"download string failed\"); /* optional: retry with a single primary mirror */ return null; }","preventionTips":["Ensure the mirrors list is non-empty before calling.","Check connectivity/proxy/TLS when all mirrors fail.","Review per-mirror logger.Error entries for the real cause."],"tags":["network","http","download","retry","playnite"],"backgroundTag":null,"analyzedSha":"5911f4e964e628aa7a69c2030ab35101afa63067","analyzedAt":"2026-08-13T17:38:25.713Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}