rocksdanister/lively · error · RpcException
ex.Message
Error message
ex.Message
What it means
The outer catch-all of SwitchReleaseChannel: any exception inside the method (download failure, Process.Start failure, GetLatestRelease failure, OperationCanceledException on client disconnect, or the MSIX guard from error #26) is logged and re-thrown as RpcException(StatusCode.Internal) with the inner Message as detail. Because it catches System.Exception, the original exception type is lost to the client; only the message string survives.
Source
Thrown at src/Lively/Lively/RPC/AppUpdateServer.cs:115
var isRequestedBetaChannel = request.Channel == ReleaseChannel.Beta;
var isCurrentBetaChannel = Constants.ApplicationType.IsTestBuild;
if (isCurrentBetaChannel && isRequestedBetaChannel || !(isCurrentBetaChannel || isRequestedBetaChannel))
return await Task.FromResult(new Empty());
var (SetupUri, SetupFileName, _) = await updater.GetLatestRelease(isRequestedBetaChannel);
var filePath = Path.Combine(Constants.CommonPaths.TempDir, SetupFileName);
await downloader.DownloadFile(SetupUri, filePath, null, context.CancellationToken);
// Run setup in silent mode.
Process.Start(filePath, "/SILENT /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS");
// Inno installer will auto retry, waiting for application exit.
App.QuitApp();
}
catch (Exception ex)
{
Logger.Error(ex);
throw new RpcException(new Status(StatusCode.Internal, ex.Message));
}
return await Task.FromResult(new Empty());
}
public override Task<UpdateResponse> GetUpdateStatus(Empty _, ServerCallContext context)
{
return Task.FromResult(new UpdateResponse()
{
Status = (UpdateStatus)((int)updater.Status),
Changelog = string.Empty,
Url = updater.LastCheckUri?.OriginalString ?? string.Empty,
FileName = updater.LastCheckFileName ?? string.Empty,
Version = updater.LastCheckVersion?.ToString() ?? string.Empty,
Time = Timestamp.FromDateTime(updater.LastCheckTime.ToUniversalTime()),
});
}
public override async Task SubscribeUpdateChecked(Empty _, IServerStreamWriter<Empty> responseStream, ServerCallContext context)View on GitHub (pinned to c1036feb66)
Solutions
- Read the gRPC detail (inner.Message) and the server NLog to identify the real failure step.
- For download/cancel failures, retry SwitchReleaseChannel once connectivity returns.
- For Process.Start failures, confirm the downloaded installer exists at Constants.CommonPaths.TempDir and isn't blocked by AV/SmartScreen.
Example fix
// before
catch (Exception ex)
{
Logger.Error(ex);
throw new RpcException(new Status(StatusCode.Internal, ex.Message));
}
// after: map specific causes to fitting status codes and preserve the cause type
catch (OperationCanceledException)
{
throw new RpcException(new Status(StatusCode.Cancelled, "Channel switch cancelled."));
}
catch (IOException ex)
{
throw new RpcException(new Status(StatusCode.Unavailable, $"Download failed: {ex.Message}"));
}
catch (Exception ex)
{
Logger.Error(ex);
var trailers = new Metadata { { "cause-exception", ex.GetType().FullName } };
throw new RpcException(new Status(StatusCode.Internal, ex.Message), ex, trailers);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
DialogService.Warn("Offline \u2014 cannot switch release channel now.");
return;
}
if (PackageUtil.IsRunningAsPackaged)
{
DialogService.Warn("Channel switching requires the desktop build.");
return;
} Try / catch
try
{
await client.SwitchReleaseChannelAsync(req, cancellationToken: cts.Token);
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.Internal)
{
Logger.Error(ex, "Channel switch failed: {Detail}", ex.Status.Detail);
if (ex.Status.Detail.Contains("msix"))
{
// prompt user to install the desktop build
}
else
{
// schedule a retry once connectivity returns
}
} Prevention
- Don't catch Exception just to re-wrap as Internal; map specific failures to fitting gRPC status codes (Unavailable, Cancelled, FailedPrecondition).
- Attach the inner exception type via gRPC metadata/trailers so the client can branch without parsing the message string.
- Validate preconditions (network, MSIX, disk space) before starting the download so most failures never reach the catch-all.
When it happens
Trigger: SwitchReleaseChannel fails at any step: downloader.DownloadFile throws (network/disk/cancellation), Process.Start throws (installer missing or blocked), updater.GetLatestRelease throws, or the MSIX guard (#26) fires first and is re-wrapped here.
Common situations: Transient network drop during the installer download. Antivirus/SmartScreen blocking the Inno installer launch. TempDir not writable. Client cancels mid-download. Running on MSIX (this catch wraps error #26 into a generic Internal).
Related errors
- msix not supported.
- Couldn't refresh tokens. You have to log in again
- Auth code value cannot be null.
- xaml island gif player not available.
- Program wallpaper on MSIX package not allowed.
AI-assisted analysis of rocksdanister/lively@c1036feb66 (2026-08-13).
Data as JSON: /api/errors/0964126b22904b92.
Report an issue: GitHub.