JosefNemec/Playnite · critical · Exception
Failed to download installer manifest.
Error message
Failed to download installer manifest.
What it means
Thrown by MainViewModel.GetInstallerManifest after every URL in the candidate list fails. The loop tries DownloadStringTaskAsync per URL, logs each per-URL failure, and only throws the generic message when none succeed. So the real cause (DNS, 404, TLS, proxy, offline) is in the preceding logger.Error entries — this throw is the aggregate failure.
Source
Thrown at source/Tools/PlayniteInstaller/MainViewModel.cs:258
webClient = null;
}
}
private async Task<List<string>> TryDownloadManifest(List<string> urls)
{
foreach (var url in urls)
{
try
{
return ParseList(await webClient.DownloadStringTaskAsync(url));
}
catch (Exception e)
{
logger.Error(e, $"Failed to download installer manifest from {url}");
}
}
throw new Exception("Failed to download installer manifest.");
}
private async Task<bool> TryDownloadInstaller(List<string> urls)
{
foreach (var url in urls)
{
try
{
await webClient.DownloadFileTaskAsync(url, App.InstallerDownloadPath);
return true;
}
catch (WebException webExp)
{
if (webExp.Status == WebExceptionStatus.RequestCanceled)
{
return false;
}
else
View on GitHub (pinned to 5911f4e964)
Solutions
- Inspect the preceding log lines — each per-URL 'Failed to download installer manifest from <url>' carries the actual WebException/inner exception.
- Verify network connectivity and DNS resolution for each URL in the list; test with a browser or `curl`.
- Configure/whitelist the proxy and required hosts, then retry the installer manifest fetch.
- If a specific URL is permanently 404, update the manifest URL list to the current Playnite distribution endpoint.
Example fix
// before
foreach (var url in urls)
{
try { return ParseList(await webClient.DownloadStringTaskAsync(url)); }
catch (Exception e) { logger.Error(e, $"Failed to download installer manifest from {url}"); }
}
throw new Exception("Failed to download installer manifest.");
// after (surface aggregated detail for diagnosis)
var errors = new List<Exception>();
foreach (var url in urls)
{
try { return ParseList(await webClient.DownloadStringTaskAsync(url)); }
catch (Exception e) { logger.Error(e, $"Failed to download installer manifest from {url}"); errors.Add(e); }
}
throw new AggregateException("Failed to download installer manifest from any URL.", errors); Defensive patterns
Strategy: retry
Validate before calling
if (urls == null || urls.Count == 0)
throw new InvalidOperationException("No installer manifest URLs configured."); Try / catch
Exception lastError = null;
foreach (var url in urls)
{
try { return ParseList(await webClient.DownloadStringTaskAsync(url)); }
catch (Exception e) { logger.Error(e, $"manifest fetch failed: {url}"); lastError = e; }
}
throw new Exception("Failed to download installer manifest.", lastError); // preserve inner cause Prevention
- Always surface the inner per-URL exception (AggregateException or innerException) so users see *why* it failed.
- Keep the manifest URL list current with the live distribution endpoint.
- Provide a proxy configuration path and validate DNS/TLS reachability before the installer run.
When it happens
Trigger: All installer-manifest URLs are unreachable: no network, corporate proxy blocking the hosts, the manifest moved (404), TLS handshake failure against the server, or the server is down. The exception message itself carries no detail by design.
Common situations: Offline machine; firewall/proxy blocking the Playnite update domain; the manifest hosting URL changed between releases; transient ISP outage; captive portal intercepting the request.
Related errors
- Failed to download installer file.
- Failed to download update file.
- Failed to download update manifest.
- Failed to download string from all mirrors.
- Failed to download file from all mirrors.
AI-assisted analysis of JosefNemec/Playnite@5911f4e964 (2026-08-13).
Data as JSON: /api/errors/9b0cf550bdb4ebe7.
Report an issue: GitHub.