Skip to content

fix(desktop): detect the WSL restart Windows still needs - #273

Merged
quickbeard merged 3 commits into
mainfrom
wsl-restart-required
Aug 19, 2026
Merged

quickbeard merged 3 commits into
mainfrom
wsl-restart-required

Conversation

@quickbeard

@quickbeard quickbeard commented Aug 19, 2026 •

Copy link
Copy Markdown
Owner

Problem

On a Windows 10 machine that never had WSL 2, installing it from the create-sandbox dialog reported success, and creating the sandbox then failed — including after a restart — with:

Error invoking remote method 'sandbox-add-default': Error: wsl --import failed for codev-default-sandbox: exited 4294967295

Confirmed on the affected machine: wsl --version reports 2.x while wsl --status fails with Wsl/WSL_E_WSL_OPTIONAL_COMPONENT_REQUIRED. Three bugs compound:

  1. The elevated installer never enabled the WSL optional component. Windows 10 requires Microsoft-Windows-Subsystem-Linux even for the standalone WSL MSI; the script only enabled VirtualMachinePlatform, so every distro command could only fail.
  2. The install reported "installed" when Windows still needed a restart. dism/msiexec exit 3010 (ERROR_SUCCESS_REBOOT_REQUIRED) was mapped to 0, and the follow-up probe was wsl --version — which answers straight from the MSI before any feature is active.
  3. The real diagnostic was thrown away. wsl.exe prints its errors to stdout (UTF-16LE), not stderr; the provider surfaced stderr only, reducing everything to exited 4294967295 (-1 unsigned).

Fix

  • install-bundle.ts: the elevated script enables both Windows features (dism is a no-op where a feature already exists, so no build gate) and re-raises 3010 instead of mapping it to 0 — the exit code is the only signal that crosses the Start-Process -Verb RunAs boundary. Exported as WSL_INSTALL_REBOOT_REQUIRED.
  • sandbox/wsl-install.ts: exit 3010 → the restart-required state; the availability probe stays only as backstop for the wsl --install fallback path. New restartWindows() runs shutdown.exe /r /t 0 (no /f, refusals reject).
  • Create-sandbox dialogs: the restart-required state now offers a Restart Windows button with an inline confirm step (restarting closes every app), over a new sandbox-wsl-restart channel; new sandbox.wsl.restart* i18n keys (en/es).
  • @codev/sandbox wsl/provider.ts: the availability probe becomes wsl --status, which fails — and says why — exactly when running a distro would; its message is surfaced (e.g. the component-required error), so a half-installed machine is offered the now complete installer instead of a doomed import. New wslFailureDetail() includes the stdout diagnostic in every WSL error, and an import failure in the VM-unavailable HCS family appends a restart/enable-virtualization hint.
  • wsl/servers.ts (upstream-tracked): the Code side's install-wsl job treats 3010 as success with pendingRestart: true. DIVERGENCES rows updated ("Dual-path WSL install", "WSL auto-install from the sandbox dialogs").

Tests

  • Elevated script asserts both dism features and the 3010 re-raise.
  • Sandbox installer: 3010 → restart-required without consulting availability; restartWindows invokes shutdown.exe /r /t 0, surfaces refusals, refuses off-Windows.
  • Provider: availability surfaces WSL_E_WSL_OPTIONAL_COMPONENT_REQUIRED from a fake wsl.exe whose --version passes but --status fails (the affected machine's exact shape); a failing --import surfaces its UTF-16LE stdout diagnostic plus the restart hint; missing wsl.exe still gets the generic install prompt.
  • Full suites: 163 pass in @codev/sandbox, 145 in desktop, 702 in app; workspace turbo typecheck clean.

CHANGELOG entry added under Unreleased → Sandbox.

🤖 Generated with Claude Code

Quickbeard and others added 3 commits August 19, 2026 15:55
Installing WSL 2 on a machine that never had VirtualMachinePlatform ends
with dism/msiexec exit 3010 (ERROR_SUCCESS_REBOOT_REQUIRED), but the
elevated script mapped that to 0 and the follow-up probe was
`wsl --version`, which answers from the freshly installed MSI before the
feature is active. The app then declared WSL installed and went straight
to creating the sandbox, whose `wsl --import` needs the WSL2 utility VM
and failed — as "exited 4294967295" with no explanation, because wsl.exe
prints its diagnostics to stdout while the provider only surfaced stderr.

The elevated script now re-raises 3010 (the exit code is the only signal
that crosses the RunAs boundary); the sandbox installer turns it into the
existing restart-required state and the Code side's install-wsl job into
pendingRestart. WSL command failures now include the stdout diagnostic,
and an import failure in the VM-unavailable error family adds a hint to
restart Windows or enable virtualization in firmware.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A restart-required install left the user with a sentence and a trip to
the Start menu. The create-sandbox dialogs now show a Restart Windows
button in that state: it arms an inline confirm step — restarting closes
CoDev and every other open application, and the hint says so — and then
runs shutdown.exe /r /t 0 via a new sandbox-wsl-restart channel. No /f,
so an application holding unsaved work can still hold the restart, and a
refusal (shutdown policy, an already pending shutdown) surfaces as a
toast instead of a restart that never comes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On the affected Windows 10 machine the import failure survived the
restart, and `wsl --status` named the real cause:
Wsl/WSL_E_WSL_OPTIONAL_COMPONENT_REQUIRED. Windows 10 requires the
Microsoft-Windows-Subsystem-Linux optional component even for the
standalone MSI, and the elevated install script only ever enabled
VirtualMachinePlatform — while `wsl --version`, the availability probe,
kept passing straight from the MSI.

The script now enables both features (dism is a no-op where the
component already exists, so no build gate), with 3010 from either
re-raised as before. The sandbox provider's availability probe becomes
`wsl --status`, which fails — and says why — exactly when running a
distro would, so a half-installed machine is offered the now complete
installer instead of a doomed import; its message is surfaced over the
generic install prompt, which remains for a missing wsl.exe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@quickbeard
quickbeard merged commit ba889db into main Aug 19, 2026
0 of 5 checks passed
@quickbeard
quickbeard deleted the wsl-restart-required branch August 19, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant