Orbmu2k/nvidiaProfileInspector · error · InvalidOperationException
The selected release does not contain a downloadable update…
Error message
The selected release does not contain a downloadable update package.
What it means
InvalidOperationException thrown by InplaceUpdateInstaller.PrepareAndRunAsync when the release is non-null but IsInstallable is false — the release lacks a downloadable asset (DownloadUrl/Asset) so the in-place updater has nothing to download. Same condition as the AppUpdateService-level check, repeated defensively inside the installer.
Solutions
- Verify release.IsInstallable before invoking the installer (both at UI and service level)
- Only list releases with attached binary assets as updatable
- Catch and map to a user-facing 'this release has no installable package' message
- Re-fetch the release metadata; the asset may now be attached
Example fix
// before
await installer.PrepareAndRunAsync(release);
// after
if (!release.IsInstallable) { ShowMessage("No downloadable package for this release."); return; }
await installer.PrepareAndRunAsync(release); Defensive patterns
Strategy: validation
Validate before calling
if (release is null) throw new InvalidOperationException("No release selected");
if (!release.IsInstallable) throw new InvalidOperationException("Release has no downloadable package"); Type guard
bool IsInstallableRelease(UpdateRelease release) => release is not null && release.IsInstallable && !string.IsNullOrEmpty(release.Asset?.DownloadUrl);
Try / catch
try { await installer.PrepareAndRunAsync(release); }
catch (InvalidOperationException) { MessageBox.Show("No downloadable update package for this release."); } Prevention
- Check IsInstallable before any install path, including direct installer calls
- Verify Asset and DownloadUrl are non-empty before offering the update
- Filter update lists to releases with binary assets
- Re-fetch release data if assets may have been attached after caching
When it happens
Trigger: Calling the installer directly, bypassing AppUpdateService's pre-check, with a release that has no asset; a release whose assets were stripped (source-only); IsInstallable false because asset name/URL failed parsing; race where the asset list changed between check and install.
Common situations: Updating from a release where CI didn't upload the zip; manually constructing an UpdateRelease without an Asset; testing the installer against a draft release.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- The selected release does not contain a downloadable update…
- No update release was selected.
- Base profile cannot be deleted.
- The selected update package format is not supported.
AI-assisted analysis of Orbmu2k/nvidiaProfileInspector@2f50c388b3 (2026-09-15).
Data as JSON: /api/errors/7fc72a5c5d651e5e.
Report an issue: GitHub.
Appendix: source
Thrown at nvidiaProfileInspector/Common/Updates/InplaceUpdateInstaller.cs:20
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
namespace nvidiaProfileInspector.Common.Updates
{
public sealed class InplaceUpdateInstaller : IUpdateInstaller
{
public async Task PrepareAndRunAsync(UpdateRelease release)
{
if (release == null)
throw new InvalidOperationException("No update release was selected.");
if (!release.IsInstallable)
throw new InvalidOperationException("The selected release does not contain a downloadable update package.");
var tempRoot = Path.Combine(Path.GetTempPath(), "nvidiaProfileInspector-update-" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(tempRoot);
var assetPath = Path.Combine(tempRoot, SanitizeFileName(release.Asset.Name ?? "update.zip"));
await DownloadFileAsync(release.Asset.DownloadUrl, assetPath);
var sourcePath = PrepareUpdateSource(tempRoot, assetPath, release.Asset.PackageType);
var appDirectory = AppContext.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var executablePath = Assembly.GetEntryAssembly()?.Location ?? Process.GetCurrentProcess().MainModule.FileName;
var scriptPath = Path.Combine(tempRoot, "apply-update.cmd");
File.WriteAllText(scriptPath, CreateUpdateScript(Process.GetCurrentProcess().Id, tempRoot, sourcePath, appDirectory, executablePath));
Process.Start(new ProcessStartInfo
{
FileName = scriptPath,
UseShellExecute = true,View on GitHub (pinned to 2f50c388b3)