Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Notable changes to Wisp are recorded here.

## Unreleased

- Report which check the update helper failed when an update cannot start, and show how to reinstall when this copy of Wisp does not match the registered installation. Automatic update attempts stop for the session after such a rejection; Install update remains available from the dashboard.

## 2.6.13 - 2026-10-17

- Keep the HUD renderer running when a native graphics allocation fails; report the failure and restart the renderer instead of closing Wisp.
Expand Down
29 changes: 22 additions & 7 deletions src/Wisp.App/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,7 @@ internal async Task<ApplicationUpdateStartResult> TryBeginApplicationUpdateAsync
return (false, "Application updates were paused. Review the update again when available.");
}
ApplicationUpdateHandoff handoff;
var launchedAt = DateTimeOffset.UtcNow;
try
{
handoff = ApplicationUpdateLauncher.Launch(installer);
Expand Down Expand Up @@ -730,17 +731,31 @@ InvalidOperationException or ArgumentException or Win32Exception or
}
if (handoffState != ApplicationUpdateHandoffState.Ready)
{
RecordSupplementarySignal("update", "update", handoffState == ApplicationUpdateHandoffState.TimedOut ? "timeout" : "failure", "install-handoff",
incident: Supplementary.SupplementaryIncidentSchema.Create("update",
handoffState == ApplicationUpdateHandoffState.TimedOut ? "timeout" : "update-verification-failed", "update-install-handoff"));
string error;
var helperRejected = false;
if (handoffState == ApplicationUpdateHandoffState.HelperExited)
{
// The helper records which check failed before it exits. Report that code now,
// and stop automatic attempts when the same check fails again in this session.
var exit = ApplicationUpdateLauncher.DescribeHelperExit(handoff.ExitCode, launchedAt);
RecordSupplementarySignal("update", "update", "failure", "install-handoff", incident: exit.Incident);
error = exit.Status;
helperRejected = exit.Permanent;
}
else
{
RecordSupplementarySignal("update", "update", handoffState == ApplicationUpdateHandoffState.TimedOut ? "timeout" : "failure", "install-handoff",
incident: Supplementary.SupplementaryIncidentSchema.Create("update",
handoffState == ApplicationUpdateHandoffState.TimedOut ? "timeout" : "update-verification-failed", "update-install-handoff"));
error = handoffState == ApplicationUpdateHandoffState.TimedOut
? "The update helper did not become ready in time. Wisp stayed open and no files were installed."
: "The update helper could not verify this installation. Wisp stayed open and no files were installed.";
}
handoff.StopIfRunning();
_applicationUpdateHandoffActive = false;
_controller.Runs.CancelMetadataClosePreparation();
var error = handoffState == ApplicationUpdateHandoffState.TimedOut
? "The update helper did not become ready in time. Wisp stayed open and no files were installed."
: "The update helper could not verify this installation. Wisp stayed open and no files were installed.";
_controller.ViewModel.UpdateApplicationUpdateStatus(error, "Try again", canCheck: true);
return (false, error);
return new ApplicationUpdateStartResult(false, error, HelperRejected: helperRejected);
}
}

Expand Down
16 changes: 14 additions & 2 deletions src/Wisp.App/AppController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -723,9 +723,19 @@ private static ApplicationUpdateDetails ApplicationUpdateDetailsFrom(UpdateRelea
}
}

// Once automatic installation has stopped for the session (the update helper is missing or
// rejected this installation), the periodic check points at the full installer instead of
// promising an installation that cannot happen. The buttons still try once per click.
private bool AutomaticInstallationStopped => _automaticInstaller is { HandoffUnavailable: true };

private static string ManualInstallStatus(SemanticVersion version) =>
$"Wisp {ApplicationVersionInfo.Format(version)} could not be installed automatically. Download and run the full installer from wispoverlay.com.";

private void ShowAvailableApplicationUpdate(UpdateRelease release) =>
ViewModel.UpdateApplicationUpdateStatus(
$"Wisp {ApplicationVersionInfo.Format(release.Version)} is available. Wisp will update and restart after Forza closes.",
AutomaticInstallationStopped
? ManualInstallStatus(release.Version)
: $"Wisp {ApplicationVersionInfo.Format(release.Version)} is available. Wisp will update and restart after Forza closes.",
"Update",
canCheck: true,
isUpdateAvailable: true);
Expand All @@ -737,7 +747,9 @@ private bool TryShowPendingApplicationUpdate(bool canCheck = true)
return false;
}
ViewModel.UpdateApplicationUpdateStatus(
$"Wisp {ApplicationVersionInfo.Format(pending.Version)} is verified and ready to install.",
AutomaticInstallationStopped
? ManualInstallStatus(pending.Version)
: $"Wisp {ApplicationVersionInfo.Format(pending.Version)} is verified and ready to install.",
"Install update",
canCheck,
isUpdateAvailable: true);
Expand Down
Loading
Loading