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

  1. Verify release.IsInstallable before invoking the installer (both at UI and service level)
  2. Only list releases with attached binary assets as updatable
  3. Catch and map to a user-facing 'this release has no installable package' message
  4. 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

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


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)