{"record":{"id":"a653bd52f009828b","repo":"rocksdanister/lively","slug":"msix-not-supported","errorCode":null,"errorMessage":"msix not supported.","messagePattern":"msix not supported\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Lively/Lively/RPC/AppUpdateServer.cs","lineNumber":95,"sourceCode":"                    Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new ThreadStart(delegate\n                    {\n                        MessageBox.Show($\"{Properties.Resources.LivelyExceptionAppUpdateFail}\\n\\nException:\\n{ex}\", Properties.Resources.TextError, MessageBoxButton.OK, MessageBoxImage.Error);\n                    }));\n                }\n            }\n            catch (Exception ex)\n            {\n                Logger.Error(ex);\n            }\n            return Task.FromResult(new Empty());\n        }\n\n        public override async Task<Empty> SwitchReleaseChannel(SwitchReleaseChannelRequest request, ServerCallContext context)\n        {\n            try\n            {\n                if (PackageUtil.IsRunningAsPackaged)\n                    throw new InvalidOperationException(\"msix not supported.\");\n\n                var isRequestedBetaChannel = request.Channel == ReleaseChannel.Beta;\n                var isCurrentBetaChannel = Constants.ApplicationType.IsTestBuild;\n\n                if (isCurrentBetaChannel && isRequestedBetaChannel || !(isCurrentBetaChannel || isRequestedBetaChannel))\n                    return await Task.FromResult(new Empty());\n\n                var (SetupUri, SetupFileName, _) = await updater.GetLatestRelease(isRequestedBetaChannel);\n                var filePath = Path.Combine(Constants.CommonPaths.TempDir, SetupFileName);\n\n                await downloader.DownloadFile(SetupUri, filePath, null, context.CancellationToken);\n                // Run setup in silent mode.\n                Process.Start(filePath, \"/SILENT /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS\");\n                // Inno installer will auto retry, waiting for application exit.\n                App.QuitApp();\n            }\n            catch (Exception ex)\n            {","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/rocksdanister/lively/blob/c1036feb664960722e34bf4309042c247d6a909d/src/Lively/Lively/RPC/AppUpdateServer.cs#L77-L113","documentation":"Thrown by AppUpdateServer.SwitchReleaseChannel when PackageUtil.IsRunningAsPackaged is true. Channel switching works by downloading an Inno Setup .exe and launching it with /SILENT, which an MSIX/AppContainer install cannot do, so the server refuses up front with InvalidOperationException. That exception is then caught by the method's outer catch and re-raised to the client as RpcException(StatusCode.Internal).","triggerScenarios":"A gRPC client calls SwitchReleaseChannel while Lively is installed/running as an MSIX package (PackageUtil.IsRunningAsPackaged == true).","commonSituations":"User installed the Store (MSIX) build and clicks 'switch to beta/stable' in the UI. The client code is shared between desktop and Store builds but only the desktop build can switch channels via the Inno installer.","solutions":["Use the non-MSIX desktop build, which can run the Inno installer and switch channels.","Hide the release-channel switch in the UI when PackageUtil.IsRunningAsPackaged is true.","For MSIX, switch channels through the Store/MSIX deployment mechanism instead of an Inno installer."],"exampleFix":"// before\nif (PackageUtil.IsRunningAsPackaged)\n    throw new InvalidOperationException(\"msix not supported.\");\n\n// after: map to a gRPC FAILED_PRECONDITION so the client can show a precise message\nif (PackageUtil.IsRunningAsPackaged)\n    throw new RpcException(new Status(StatusCode.FailedPrecondition,\n        \"Channel switching is not supported in the MSIX/Store build.\"));","handlingStrategy":"validation","validationCode":"if (PackageUtil.IsRunningAsPackaged)\n{\n    DialogService.Warn(\"Release-channel switching requires the desktop build.\");\n    return;\n}\nawait client.SwitchReleaseChannelAsync(new SwitchReleaseChannelRequest { Channel = request.Channel });","typeGuard":"static bool CanSwitchReleaseChannel() => !PackageUtil.IsRunningAsPackaged;","tryCatchPattern":"try\n{\n    await client.SwitchReleaseChannelAsync(req);\n}\ncatch (RpcException ex) when (ex.Status.Detail.Contains(\"msix\"))\n{\n    Logger.Warn(ex, \"Channel switch blocked on MSIX build.\");\n}","preventionTips":["Gate the channel-switch UI on !PackageUtil.IsRunningAsPackaged so the option is invisible in Store builds.","Return a precise gRPC status (FailedPrecondition) instead of generic Internal so the client can branch cleanly.","Document that Store builds must use the Store for channel/version changes."],"tags":["grpc","msix","update","rpc","csharp"],"backgroundTag":null,"analyzedSha":"c1036feb664960722e34bf4309042c247d6a909d","analyzedAt":"2026-08-13T13:03:12.648Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}