{"record":{"id":"d0feae2e36bae868","repo":"JosefNemec/Playnite","slug":"failed-to-download-file-from-all-mirrors","errorCode":null,"errorMessage":"Failed to download file from all mirrors.","messagePattern":"Failed to download file from all mirrors\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"source/Playnite/Common/Web/Downloader.cs","lineNumber":248,"sourceCode":"        }\r\n\r\n        public async Task DownloadFileAsync(IEnumerable<string> mirrors, string path, Action<DownloadProgressChangedEventArgs> progressHandler)\r\n        {\r\n            logger.Debug($\"Downloading data async from multiple mirrors.\");\r\n            foreach (var mirror in mirrors)\r\n            {\r\n                try\r\n                {\r\n                    await DownloadFileAsync(mirror, path, progressHandler);\r\n                    return;\r\n                }\r\n                catch (Exception e)\r\n                {\r\n                    logger.Error(e, $\"Failed to download {mirror} file.\");\r\n                }\r\n            }\r\n\r\n            throw new Exception(\"Failed to download file from all mirrors.\");\r\n        }\r\n\r\n        public void DownloadFile(IEnumerable<string> mirrors, string path)\r\n        {\r\n            logger.Debug($\"Downloading data from multiple mirrors.\");\r\n            foreach (var mirror in mirrors)\r\n            {\r\n                try\r\n                {\r\n                    DownloadFile(mirror, path);\r\n                    return;\r\n                }\r\n                catch (Exception e)\r\n                {\r\n                    logger.Error(e, $\"Failed to download {mirror} file.\");\r\n                }\r\n            }\r\n\r","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/JosefNemec/Playnite/blob/5911f4e964e628aa7a69c2030ab35101afa63067/source/Playnite/Common/Web/Downloader.cs#L230-L266","documentation":"Thrown by the async Downloader.DownloadFileAsync-over-mirrors path when every mirror's DownloadFileAsync call raised an exception (each caught and logged). It is a bare Exception; per-mirror errors are only in the log, not aggregated.","triggerScenarios":"All mirrors fail (network down, 4xx/5xx, TLS, timeout, write failure to the destination path); empty mirrors list throws without attempting any download; destination directory missing or unwritable for every mirror.","commonSituations":"Downloading game covers/metadata during a network outage; mirrors misconfigured; AV or proxy blocking the hosts; destination folder deleted between calls.","solutions":["Inspect the per-mirror logger.Error entries for the real failure per URL.","Confirm the destination directory exists and is writable before downloading.","Verify at least one mirror is reachable and the list is non-empty.","Retry when network/proxy/cert issues are resolved."],"exampleFix":"// before\nawait downloader.DownloadFileAsync(mirrors, path, progress);\n\n// after — guard dest dir and aggregate per-mirror failures\nDirectory.CreateDirectory(Path.GetDirectoryName(path));\nList<Exception> failures = new List<Exception>();\nforeach (var m in mirrors ?? Enumerable.Empty<string>())\n{\n    try { await downloader.DownloadFileAsync(m, path, progress); return; }\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.\");\nDirectory.CreateDirectory(Path.GetDirectoryName(path));","typeGuard":"static bool HasMirrors(IEnumerable<string> m) => m != null && m.Any(s => !s.IsNullOrWhiteSpace());","tryCatchPattern":"try { await downloader.DownloadFileAsync(mirrors, path, progress); }\ncatch (Exception ex) { logger.Error(ex, \"download file failed\"); /* retry on transient network recovery */ }","preventionTips":["Ensure the destination directory exists and is writable.","Confirm at least one mirror is reachable.","Inspect per-mirror log errors to localize the failure."],"tags":["network","http","download","retry","async","playnite"],"backgroundTag":null,"analyzedSha":"5911f4e964e628aa7a69c2030ab35101afa63067","analyzedAt":"2026-08-13T17:38:25.713Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}