fix(setup): explain WSL platform install download failures - #2
Closed
RomneyDa wants to merge 2 commits into
Closed
Conversation
joelagnel
force-pushed
the
feature/local-ai-llama-server-code-only
branch
2 times, most recently
from
August 21, 2026 00:23
1e4c2f7 to
2bcf986
Compare
wsl.exe in System32 is a stub; the real WSL ships out of band. When WSL is absent, wsl --install resolves the package to download by calling https://api.github.com/repos/Microsoft/WSL/releases/latest — a URL embedded in the stub, with no command-line option to redirect it at the Microsoft Store. Unauthenticated GitHub API calls are capped at 60/hour per IP, so a machine behind shared egress (corporate NAT, VPN, cloud hosts, CI, remote-accessed lab hardware) can find the quota already spent by unrelated traffic. wsl.exe then prints "Forbidden (403)." and exits 1. Setup could report none of that. The installer must run elevated, elevation requires ShellExecute, and ShellExecute cannot redirect stdout/stderr, so the only thing reaching the log was "WSL platform install failed with exit code 1" — with no way to tell a rate limit from a broken network, a policy block, or a genuine WSL fault. Read the same quota endpoint wsl.exe depends on, and use it twice: before elevating, to fail without raising an administrator prompt for an install that cannot succeed, and after a non-zero exit, to name the likely cause. /rate_limit is itself exempt from the quota, so the probe is free, and a probe that fails never turns a recoverable failure into a hard one. Both messages point at the Microsoft Store, which does not go through the GitHub API. ensure-wsl-platform becomes retryable: inspection and wsl --install are both idempotent, and the failures seen here — an exhausted quota, a declined elevation prompt — are transient. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L8LRNTZ5fBgjGwmtBCrSp3
Naming the cause is not enough when the cause is someone else's traffic on a shared IP: the user still has to get WSL onto the machine. Every failure message now ends with two concrete routes, in order of what works while the GitHub quota is still spent. The Microsoft Store route is listed first precisely because it does not go through the GitHub API, so it succeeds during the window that defeats wsl --install. It carries both the Store page and a winget one-liner, so the fix is copyable rather than a hunt. The elevated wsl --install command is second, for once the quota frees up. The failure surface already cooperates: CompletePage renders the message in a wrapping monospace card and lifts the first URL into a clickable link, so the line breaks and bare commands survive to the user unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L8LRNTZ5fBgjGwmtBCrSp3
RomneyDa
force-pushed
the
fix/wsl-install-diagnostics
branch
from
August 21, 2026 00:31
2bf1be3 to
9826445
Compare
Owner
|
Rewritten compactly and safely, with Dallin's authorship preserved, in the official OpenClaw PR openclaw#1178: openclaw#1178 The replacement implementation is commit 1458856. Closing this PR as superseded. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on openclaw#1178 — base is that PR's branch, so this diff is only the three files below.
What broke
Setup failed on an ARM64 Windows 11 (build 28000) box at
preflight-wsl:That message is everything the engine knew. Tracing it took hours; the actual cause was one line
wsl.exeprinted and we discarded:C:\Windows\System32\wsl.exeis a stub — the real WSL ships out of band. When WSL is absent,wsl --installresolves the package to download by callinghttps://api.github.com/repos/Microsoft/WSL/releases/latest. That URL is embedded in the stub (it is the only URL in the binary), and this build has no--web-download/--from-storeoption strings, so nothing redirects it at the Store.Unauthenticated GitHub API calls are capped at 60/hour per IP. On the failing machine:
It is a remote-accessed lab machine behind shared egress, and the quota was pegged at 60/60 in two windows six hours apart — spent by unrelated traffic, not by OpenClaw. Corporate NAT, VPN, cloud hosts and CI runners are all exposed to the same thing. Note the cap is per IP, so a fleet provisioning behind one NAT shares one 60/hour bucket, and retries drain it faster.
Corroborating evidence that the install died before doing any work:
dism.loguntouched, zeroAppXDeploymentServer/Operationalevents, bothMicrosoft-Windows-Subsystem-LinuxandVirtualMachinePlatformstill Disabled.Why the error was invisible
InstallWslPlatformAsyncmust run the installer elevated, elevation requiresShellExecute, andShellExecutecannot redirect stdout/stderr. The process exit code was the only signal — and exit1cannot distinguish a rate limit from a broken network, a policy block, or a real WSL fault.The fix
Name the cause. Read the same quota endpoint
wsl.exedepends on, and use it twice: before elevating, to fail without raising an administrator prompt for an install that cannot succeed; and after a non-zero exit, to name the likely cause./rate_limitis itself exempt from the quota, so the probe is free, and a probe that fails returnsnulland never turns a recoverable failure into a hard one.Then hand the user a way out. Naming the cause is not enough when the cause is someone else's traffic on a shared IP — the user still has to get WSL onto the box. Every failure message now ends with two concrete routes:
The Store route is first because it does not touch the GitHub API, so it works during the window that defeats
wsl --install— verified from the affected machine (winget show --id 9P9TQF7MRM4R --source msstoreresolves while the API returns 403). This also composes with how setup already behaves:WslViabilityInspectoris read-only andEnsureWslPlatformStepreturns early when WSL isReady, so a user who installs WSL by any means simply walks past both steps on the next run.The failure surface needs no changes —
CompletePagerenders the message in a wrapping monospace card and lifts the first URL into a clickable button, so the line breaks and bare commands survive intact.ensure-wsl-platformalso becomes retryable — inspection andwsl --installare both idempotent, and the failures seen here (exhausted quota, declined elevation prompt) are transient.Before / after on the failing machine:
WSL platform install failed with exit code 1.WSL is not installed, and OpenClaw cannot install it right now: wsl --install downloads WSL from GitHub, and this machine has already used its full unauthenticated GitHub API quota (60/60), which resets at 17:19 local time. Shared networks reach that cap without any help from OpenClaw.+ the self-install block aboveVerification
OpenClaw.SetupEngine.Testspass — 933 existing plus 13 new covering the wording, the exhaustion predicate, the self-install routes, and the pre-elevation abort (asserting the probe runs exactly once, i.e. no elevation prompt is raised).QueryGitHubQuotaAsyncagainst the real endpoint on the failing machine:limit=60 remaining=0 used=60 resets=17:19 exhausted=True, matching the raw API exactly.Deliberately not done
cmd /c "… > out 2> err"wrapper — I verified the quoting survivesShellExecute— but it makes the UAC prompt read "Windows Command Processor" instead ofwsl.exe, and puts an elevated process writing into a user-writable path. A signed self-elevating helper is the right long-term answer..msixbundle, reusingLocalAiArtifactInstallerandPinnedArtifactthe way the CUDA runtime and GGUF models already do. This is the real fleet fix — it removes the GitHub API from the provisioning path entirely and pins one WSL version across machines — but it is a behaviour change deserving its own review, and the MSIX install step is unverified.Adjacent defects, not fixed here
CommandRunner.RunAsyncreturns-1on timeout, discarding the process's real exit code (CommandRunner.cs:192). That file is not touched by feat: add managed local AI with llama-server openclaw/openclaw-windows-node#1178.wsl --versionprobe is too tight for a cold first invocation — measured 26-31ms warm, but the failing run burned the full 5s and recorded a synthetic timeout. It also gates the Capabilities page's Next click throughInitializeLocalAiReviewAsync, producing a visible UI hang when WSL is absent.CompletePage.xaml.cs:80labels the help link "Update WSL →" whenever the message contains "WSL"; "Install WSL →" would read better in this case.🤖 Generated with Claude Code
https://claude.ai/code/session_01L8LRNTZ5fBgjGwmtBCrSp3