WSL backend never starts in a distro with automount disabled: wslpath conversion fails and the app silently falls back to Windows
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
Description
What happened
I enabled the WSL backend in the desktop app and pointed it at my distro. In parallel mode the switch stays on and nothing reports an error, but the WSL environment never becomes usable: it never appears as connected, "Open WSL folder" is not offered, and adding a project under the distro is refused. It looks like the setting simply did nothing. I only found the cause by reading the trace log.
Switching to WSL-only and restarting does surface it, as a modal (quoted under Evidence). After dismissing it, the WSL backend picker in Settings > Connections reads "Off", even though the preference is still enabled on disk.
The distro is a hardened sandbox image: /etc/wsl.conf sets [automount] enabled=false on purpose, so no Windows drive is mounted inside it.
Diagnosis
The WSL backend cannot pass preflight in any distro where Windows drives are not mounted, because the server tree is staged on the Windows filesystem and then reached from inside the distro through a wslpath translation that has nothing to translate to.
Chain, from v0.0.34 source:
DesktopWslServerTree.ts:123stages the server bundle atjoin(environment.stateDir, "wsl-server-tree"), i.e. always on the Windows filesystem. Extraction succeeded here: 152 MB written under the Windows state dir. No setting relocates this.DesktopBackendConfiguration.ts:303converts that Windows entry path viawslEnv.windowsToWslPath.windowsToWslPathImpl(DesktopWslEnvironment.ts:653-685) runswsl.exe -d <distro> -- wslpath -u <path>withstderr: "ignore", and returnsOption.none()on a non-zero exit.- With automount disabled there is no
C:to/mnt/cmapping, sowslpathwrites nothing to stdout, writeswslpath: <path>to stderr, and exits 1. DesktopBackendConfiguration.ts:304-310maps that toFailed { reason: "wslpath conversion failed for …", fatal: false }.- Non-fatal means
WSL_TRANSIENT_PREFLIGHT_RETRY_LIMIT = 12(DesktopBackendConfiguration.ts:238) applies. The attempt is retried with backoff (observed 1s, 2s, 4s, 8s, 10s, 10s), thenDesktopBackendManager.ts:776logs "backend preflight failed repeatedly; surfacing and falling back" and the app reverts to the Windows backend.
This condition is permanent, not transient: with automount off it can never succeed, so the retry budget is spent on every enable and the outcome is always the fallback.
Two related spots, noted only because the same setup hits them: ensureNodePty (DesktopWslEnvironment.ts:390-401) translates windowsRepoRoot through the same wslpath call and so carries the identical dependency on mounted drives, and getDistroIpImpl (DesktopWslEnvironment.ts:689-717) shells out to hostname -I in a minimal distro that ships neither hostname nor ip.
Visibility differs by mode. DesktopBackendPool.ts:232 notes a primary preflight failure "only happens in wsl-only mode", and handlePrimaryPreflightFailure (:234-247) is the only path raising a dialog. In parallel mode the WSL backend is a secondary with no equivalent path, so the identical failure is silent and discoverable only in the trace. The reason string is already user-ready, it just never reaches the user in the mode most people try first.
Secondary defect: the picker contradicts the dialog. The non-fatal path calls applyWslWindowsFallbackInMemory, which deliberately does not persist ("so the app opens without overwriting the user's WSL preference"). Confirmed on disk after the restart: desktop-settings.json still holds wslBackendEnabled: true, wslOnly: true, so the dialog's "retry next time" promise is accurate. But the Connections picker reads in-memory state (ConnectionsSettings.tsx:2827) and renders "Off". Within seconds the user is told the preference survives and shown a control saying it did not. Nothing is lost, but it invites re-setting a preference that was never unset.
Steps to reproduce
-
Install any WSL2 distro whose
/etc/wsl.confcontains:[automount] enabled=falsethen
wsl --shutdownand restart the distro so it takes effect. -
Confirm the translation is impossible there:
wsl.exe -d <distro> -- wslpath -u "C:/Users"gives empty stdout,wslpath: C:/Userson stderr, exit code 1. -
In the desktop app, enable the WSL backend and select that distro.
-
Parallel mode: the server tree extracts to
<state dir>\wsl-server-tree\<version>on the Windows side, preflight retries 12 times, then falls back to the Windows backend with no user-visible error. No server process ever runs inside the distro. -
Switch the picker to WSL-only and restart the app. Now the failure is surfaced as a modal ("WSL backend is still unavailable"). Dismiss it, then open Settings > Connections: the WSL backend picker reads "Off" while
desktop-settings.jsonstill containswslBackendEnabled: true, wslOnly: true.
Version
0.0.34
Environment
Windows 11 Pro 26200, Node 22.23.2, desktop app, WSL2. Distro: minimal AlmaLinux 9 sandbox image, systemd on, [interop] enabled=false, [automount] enabled=false.
Evidence
# desktop.trace.ndjson, span desktop.backendConfiguration.wslPreflight
# ENTRY = <STATE_DIR>\wsl-server-tree\0.0.34\apps\server\dist\bin.mjs
{"component":"desktop-backend-instance:wsl:<distro>",
"reason":"wslpath conversion failed for ENTRY","delayMs":1000,"effect.logLevel":"ERROR"}
# same reason repeated with delayMs 2000, 4000, 8000, 10000, 10000
{"name":"backend preflight failed repeatedly; surfacing and falling back",
"attributes":{"reason":"wslpath conversion failed for ENTRY"}}
# reproduced by hand against the same distro
$ wsl.exe -d <distro> -- wslpath -u "<STATE_DIR>/wsl-server-tree/0.0.34/apps/server/dist/bin.mjs"
stdout: (empty) stderr: wslpath: <same path> exit: 1
# wsl-only mode, modal dialog after restart (screenshot attached)
WSL backend is still unavailable
wslpath conversion failed for ENTRY
T3 Code will use the Windows backend for this launch and retry WSL the next time the app starts.
# desktop-settings.json on disk immediately after that restart,
# while Settings > Connections shows the picker as "Off" (screenshot attached)
{"wslBackendEnabled":true,"wslDistro":"<distro>","wslOnly":true}
Related issues
#5769 (open PR, "Cache Runtime locally on WSL Filesystem") looks like the right fix: it extracts the runtime into ~/.t3/runtime inside the distro and passes linuxAppRoot to ensureNodePty, but is framed as a launch-time optimization and keeps /mnt/c as a fallback. Here /mnt/c is absent rather than slow, which makes the Linux-local runtime a correctness requirement. Not a duplicate: that PR does not describe this failure mode, and the transient/fatal misclassification and the picker inconsistency are separate defects.
Fix applied or workaround
Nothing was changed on the machine. No configuration workaround exists in 0.0.34: the staging location is hardcoded to the Windows state dir, and enabling automount would defeat the point of the sandbox image.
Suggested directions, in order of preference:
- Stage and run the server tree inside the distro's own filesystem, as #5769 does.
- When
wslpathcannot translate, classify it as fatal rather than transient and surface the real cause ("Windows drives are not mounted in this distro") instead of a generic repeated preflight failure. - Surface a secondary-backend preflight failure somewhere in the UI too, not only in wsl-only mode. The reason string is already good enough to show.
- Have the Connections picker reflect the persisted preference, or say explicitly that WSL is paused for this launch, so it stops contradicting the dialog.
- Do not discard
wslpathstderr; it names the exact reason.
Filed by
claude (opus-5) via t3 triage
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with DesktopWslServerTree.ts, DesktopBackendConfiguration.ts, DesktopWslEnvironment.ts, DesktopBackendManager.ts, DesktopBackendPool.ts, and ConnectionsSettings.tsx; trace the staging, wslpath conversion, retry, fallback, and picker state paths. Review related issue #5769 for the Linux-local runtime context. Done means the selected failure behavior is user-visible and consistent, with WSL preference state no longer contradicting the fallback or dialog.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend, frontend, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 46/100