{"record":{"id":"2e144eefb489e032","repo":"Orbmu2k/nvidiaProfileInspector","slug":"the-selected-update-package-format-is-not-supported","errorCode":null,"errorMessage":"The selected update package format is not supported.","messagePattern":"The selected update package format is not supported\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"nvidiaProfileInspector/Common/Updates/InplaceUpdateInstaller.cs","lineNumber":74,"sourceCode":"\n        private static string PrepareUpdateSource(string tempRoot, string assetPath, UpdatePackageType packageType)\n        {\n            if (packageType == UpdatePackageType.Zip)\n            {\n                var extractPath = Path.Combine(tempRoot, \"extracted\");\n                ZipFile.ExtractToDirectory(assetPath, extractPath);\n                return FindUpdateRoot(extractPath);\n            }\n\n            if (packageType == UpdatePackageType.Exe)\n            {\n                var sourcePath = Path.Combine(tempRoot, \"extracted\");\n                Directory.CreateDirectory(sourcePath);\n                File.Copy(assetPath, Path.Combine(sourcePath, Path.GetFileName(Assembly.GetEntryAssembly()?.Location ?? \"nvidiaProfileInspector.exe\")));\n                return sourcePath;\n            }\n\n            throw new InvalidOperationException(\"The selected update package format is not supported.\");\n        }\n\n        private static string FindUpdateRoot(string extractPath)\n        {\n            var executableName = Path.GetFileName(Assembly.GetEntryAssembly()?.Location ?? \"nvidiaProfileInspector.exe\");\n            var executable = Directory\n                .GetFiles(extractPath, executableName, SearchOption.AllDirectories)\n                .OrderBy(path => path.Length)\n                .FirstOrDefault();\n\n            return executable == null ? extractPath : Path.GetDirectoryName(executable);\n        }\n\n        private static string CreateUpdateScript(int processId, string tempRoot, string sourcePath, string appDirectory, string executablePath)\n        {\n            return string.Join(Environment.NewLine, new[]\n            {\n                \"@echo off\",","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/Orbmu2k/nvidiaProfileInspector/blob/2f50c388b3a4d661cade66b32746bec096d1eee1/nvidiaProfileInspector/Common/Updates/InplaceUpdateInstaller.cs#L56-L92","documentation":"InvalidOperationException thrown at the end of InplaceUpdateInstaller.PrepareUpdateSource when the downloaded asset's package format matches none of the supported layouts (e.g. single portable exe vs zip with an executable tree). After extraction, FindUpdateRoot must locate the new executable; if the archive layout is unrecognized, the updater cannot determine the update source directory and throws. Called by the sourcePath property/flow.","triggerScenarios":"The release asset is a supported extension (e.g. .zip) but its inner layout changed (files nested differently, no exe at expected root); asset is a format the installer doesn't branch on (e.g. .7z, .msi, plain exe uploaded as zip); FindUpdateRoot can't find an executable named like the current entry assembly.","commonSituations":"CI packaging change in a new release renames or relocates the exe; a maintainer uploads a manually-built archive with an extra folder level; a portable single-file build where the copied asset bypasses the zip path but layout assumptions broke; renaming the exe so FindUpdateRoot's name match fails.","solutions":["Inspect the downloaded asset's actual archive layout and confirm the installer's FindUpdateRoot expectations match it","Extract manually and verify an executable named like the current assembly exists; if the release renamed the exe, update the name-matching logic","Make FindUpdateRoot match any executable instead of only the exact current exe name, then rethrow only when none is found","Only ship assets in the layout the installer supports, and add an automated test that extracts the packaged release","Add a guard that validates supported extensions before download to fail fast with a clearer message"],"exampleFix":"// before\nthrow new InvalidOperationException(\"The selected update package format is not supported.\");\n// after\nvar anyExe = Directory.EnumerateFiles(extractPath, \"*.exe\", SearchOption.AllDirectories).FirstOrDefault();\nif (anyExe == null)\n    throw new InvalidOperationException($\"No executable found in update package '{release.Asset.Name}'.\");\nreturn Path.GetDirectoryName(anyExe);","handlingStrategy":"try-catch","validationCode":"if (!string.Equals(Path.GetExtension(release.Asset?.Name), \".zip\", StringComparison.OrdinalIgnoreCase))\n    throw new InvalidOperationException(\"Unsupported update package extension\");","typeGuard":null,"tryCatchPattern":"try { var source = PrepareUpdateSource(assetPath, tempRoot); }\ncatch (InvalidOperationException ex) { Log.Error(ex, \"Unrecognized update package layout\"); ShowError(\"Update package layout not recognized; please install manually.\"); }","preventionTips":["Ship release assets only in the layout the installer supports","Add a CI test that extracts the packaged asset and runs FindUpdateRoot against it","Make FindUpdateRoot match any *.exe instead of only the exact current exe name","Fail fast on unsupported extensions before download/extraction"],"tags":["update","packaging","extraction"],"backgroundTag":"unsupported-operation","analyzedSha":"2f50c388b3a4d661cade66b32746bec096d1eee1","analyzedAt":"2026-09-15T05:23:52.218Z","contentChangedAt":"2026-09-15T05:23:52.218Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}