{"record":{"id":"0d6c888348559812","repo":"JosefNemec/Playnite","slug":"failed-to-download-installer-file","errorCode":null,"errorMessage":"Failed to download installer file.","messagePattern":"Failed to download installer file\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"critical","filePath":"source/Tools/PlayniteInstaller/MainViewModel.cs","lineNumber":287,"sourceCode":"                }\r\n                catch (WebException webExp)\r\n                {\r\n                    if (webExp.Status == WebExceptionStatus.RequestCanceled)\r\n                    {\r\n                        return false;\r\n                    }\r\n                    else\r\n                    {\r\n                        logger.Error(webExp, $\"Failed to download installer file from {url}\");\r\n                    }\r\n                }\r\n                catch (Exception e)\r\n                {\r\n                    logger.Error(e, $\"Failed to download installer file from {url}\");\r\n                }\r\n            }\r\n\r\n            throw new Exception(\"Failed to download installer file.\");\r\n        }\r\n\r\n        private void WebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)\r\n        {\r\n            ProgressValue = e.ProgressPercentage;\r\n        }\r\n\r\n        public void Cancel()\r\n        {\r\n            if (Status == InstallStatus.Downloading)\r\n            {\r\n                webClient.CancelAsync();\r\n                webClient.Dispose();\r\n                webClient = null;\r\n                Status = InstallStatus.Idle;\r\n            }\r\n            else\r\n            {\r","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/JosefNemec/Playnite/blob/5911f4e964e628aa7a69c2030ab35101afa63067/source/Tools/PlayniteInstaller/MainViewModel.cs#L269-L305","documentation":"Thrown by TryDownloadInstaller after every installer-file URL fails. The loop attempts DownloadFileTaskAsync per URL (writing to App.InstallerDownloadPath), logs WebException and generic exceptions per URL, then throws a plain 'Failed to download installer file.' when none succeed. The actionable detail lives in the per-URL logger.Error lines, not in this message.","triggerScenarios":"Manifest download (GetInstallerManifest) succeeded but the actual installer binary URLs all fail: 404 on the file, disk full / permission denied at App.InstallerDownloadPath, network drop mid-download, proxy blocking the CDN, or the installer path moved post-manifest.","commonSituations":"Disk full or no write permission for the installer download path; CDN/host returns 404 because the build was pulled; partial download then connection reset; proxy stripping Content-Length; antivirus locking the partially written file.","solutions":["Read the per-URL 'Failed to download installer file from <url>' log entries — they contain the WebException status (ProtocolError, ConnectFailure, etc.).","Confirm App.InstallerDownloadPath is writable and the volume has free space.","Retry on a stable network / different network; whitelist the installer CDN host on any proxy.","If URLs are 404, re-fetch the installer manifest to get current download links, or update Toolbox to a version pointing at valid installer URLs."],"exampleFix":"// before\nthrow new Exception(\"Failed to download installer file.\");\n\n// after (preserve causes)\nthrow new AggregateException(\"Failed to download installer file from any URL.\", errors); // where 'errors' collected per-URL exceptions\n\n// and guard the write target beforehand:\nvar dir = Path.GetDirectoryName(App.InstallerDownloadPath);\nif (!Directory.Exists(dir)) Directory.CreateDirectory(dir);","handlingStrategy":"retry","validationCode":"var dir = Path.GetDirectoryName(App.InstallerDownloadPath);\nif (!Directory.Exists(dir)) Directory.CreateDirectory(dir);\nif (!HasWriteAccess(dir)) throw new UnauthorizedAccessException($\"Cannot write to {dir}\");","typeGuard":null,"tryCatchPattern":"Exception lastError = null;\nforeach (var url in urls)\n{\n    try { await webClient.DownloadFileTaskAsync(url, App.InstallerDownloadPath); return true; }\n    catch (Exception e) { logger.Error(e, $\"installer file fetch failed: {url}\"); lastError = e; }\n}\nthrow new Exception(\"Failed to download installer file.\", lastError);","preventionTips":["Validate the download path is writable and the disk has space before starting.","Surface the per-URL WebException (status code) so 404 vs connect-failure vs disk-full is distinguishable.","Re-fetch the installer manifest if file URLs 404, to pick up corrected download links."],"tags":["installer","network","download","filesystem","retry-exhausted"],"backgroundTag":null,"analyzedSha":"5911f4e964e628aa7a69c2030ab35101afa63067","analyzedAt":"2026-08-13T17:38:25.713Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}