Skip to content

[Bug]: Windows desktop 0.0.28 gets stuck on connecting to WSL after enabling WSL support #3611

Description

@martinstepanek

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/desktop

Steps to reproduce

  1. Install and start T3 Code desktop on Windows.

  2. Use T3 Code 0.0.28.0 / file version 0.0.28.

  3. In Settings, enable the new WSL support for the Ubuntu WSL distro. The persisted desktop settings after this were:

    {"wslBackendEnabled":true,"wslDistro":"Ubuntu","wslOnly":true}
  4. Let the app restart.

  5. Restart the app again, or uninstall and reinstall the app.

  6. Install PowerShell 7 and Git for Windows, restart T3 Code, then enable WSL support again.

Expected behavior

The desktop app should connect to the WSL backend, or it should fail with an actionable error and provide a recoverable path back to the Windows backend.

Uninstalling/reinstalling should also not leave the app permanently stuck in a WSL-only startup path without an obvious recovery option.

Actual behavior

The app remains on the splash state showing connecting to WSL....

Restarting does not fix it. Uninstalling and reinstalling does not fix it because %USERPROFILE%\.t3\userdata\desktop-settings.json still contains the WSL-only settings.

Installing PowerShell 7 and Git for Windows did not fix the WSL startup loop. After installing PowerShell 7, pwsh.exe is found, so the original spawn pwsh.exe ENOENT warning is no longer the active blocker.

In the logs, WSL preflight succeeds, then the backend exits before readiness and the desktop keeps scheduling restarts. The app polls the WSL backend URL, but the child process exits with code=0 before it becomes ready. No Linux-side process ever listens on the selected WSL backend port.

Impact

Blocks work completely

Version or commit

T3 Code desktop 0.0.28.0 / file version 0.0.28

Environment

  • Windows desktop app

  • Windows version: 10.0.26200.8655

  • WSL distro: Ubuntu, WSL version 2, state Running

  • T3 settings after enabling WSL support:

    {"wslBackendEnabled":true,"wslDistro":"Ubuntu","wslOnly":true}
  • Initially, Windows pwsh.exe was not available on PATH:

    where.exe pwsh
    INFO: Could not find files for the given pattern(s).
    
  • After installing PowerShell 7, pwsh.exe is found:

    C:\Users\mstep\AppData\Local\Microsoft\WindowsApps\pwsh.exe
    
  • Git for Windows is installed and works by absolute path:

    C:\Program Files\Git\cmd\git.exe --version
    git version 2.54.0.windows.1
  • There was already a WSL-side npx t3 process listening on port 3773, so the Windows desktop selected backend port 3774.

Logs or stack traces

Initial desktop log excerpts, redacted to remove user-specific paths:

WARN component=desktop-shell-environment probe=powershell-no-profile executable=pwsh.exe
cause: Error: spawn pwsh.exe ENOENT

WARN component=desktop-shell-environment probe=powershell-profile executable=pwsh.exe
cause: Error: spawn pwsh.exe ENOENT

INFO component=desktop-bootstrap selected backend port via sequential scan
port: 3774
startPort: 3773

INFO component=desktop-window connecting splash shown

# WSL preflight in desktop.trace.ndjson appeared to complete successfully:
# - probeDistros success
# - windowsToWslPath success
# - ensureNodePty success
# - getDistroIp success
# Then desktop polled the WSL backend endpoint:
# http://172.x.x.x:3774/.well-known/t3/environment

ERROR component=desktop-backend-instance:primary backend exited unexpectedly; restart scheduled
reason: code=0
delayMs: 500

After installing PowerShell 7 and Git for Windows, re-enabling WSL reproduced the same startup loop without the pwsh.exe ENOENT blocker.

Fresh WSL-mode behavior:

# WSL preflight still succeeds:
# - probeDistros success
# - windowsToWslPath success
# - ensureNodePty success
# - getDistroIp success

# Desktop polls:
http://172.19.227.101:3774/.well-known/t3/environment

# server-child.log repeats child starts and clean exits with no stdout/stderr:
backend child process session start ... runId=d98663cc90e4 ... pid=3464 port=3774 cwd=C:\Users\mstep
backend child process session end   ... runId=d98663cc90e4 ... pid=3464 code=0

Captured T3 WSL backend child command line from Windows process inspection:

wsl.exe -d Ubuntu --exec env \
  "PATH=/home/stepanek/.nvm/versions/node/v18.20.8/bin:...:/mnt/c/Program Files/Git/cmd:..." \
  /home/stepanek/.nvm/versions/node/v18.20.8/bin/node \
  /mnt/c/Users/mstep/AppData/Local/Programs/t3code/resources/app.asar.unpacked/apps/server/dist/bin.mjs \
  --bootstrap-fd 0

The child exits with code=0 before readiness. Since there is no server output at all in this path, this looks like either the WSL backend bootstrap payload/FD path is failing before logging, or the server process is treating the bootstrap input as complete/empty and exiting cleanly.

No Linux-side process ever listens on 3774; ss -ltnp in WSL only shows the existing unrelated/local 127.0.0.1:3773 T3 server.

After disabling WSL mode, the Windows backend produces normal server logs, for example:

runId=f4c7297cd553
Listening on http://127.0.0.1:3774
POST /oauth/token 200

Workaround

Stop the Windows T3 Code process and edit:

%USERPROFILE%\.t3\userdata\desktop-settings.json

Change the settings from:

{"wslBackendEnabled":true,"wslDistro":"Ubuntu","wslOnly":true}

to:

{"wslBackendEnabled":false,"wslDistro":"Ubuntu","wslOnly":false}

Then restart T3 Code. The app boots again using the Windows backend on 127.0.0.1:3774.

Confirmed root cause from source/runtime investigation

The WSL preflight is selecting Node v18.20.8 from nvm default, even though the server package declares engines.node = "^22.16 || ^23.11 || >=24.10".

In apps/server/src/bin.ts, the packaged server entrypoint is gated by:

if (import.meta.main) {
  Command.run(cli, { version: packageJson.version })...
}

Runtime check on this machine:

/home/stepanek/.nvm/versions/node/v18.20.8/bin/node -> import.meta.main is undefined
/home/stepanek/.nvm/versions/node/v22.22.1/bin/node -> import.meta.main is true

So with Node 18, the bundled WSL backend module loads and exits 0 before the CLI/server starts. That matches the desktop symptom: no WSL server ever listens on the selected port, desktop keeps polling /.well-known/t3/environment, and the splash remains stuck at "connecting to WSL...".

Why preflight misses it: apps/desktop/src/wsl/DesktopWslEnvironment.ts passes the server engine range into the WSL node resolver, but after nvm default leaves an out-of-range node on PATH, the node-pty probe can still succeed on Node 18. The code then returns { ok: true, nodePath, resolvedPath } on probe.exitCode === 0 before enforcing that the selected nodePath satisfies serverPackageJson.engines.node.

Local workaround that makes the Windows-launched WSL probe select a compatible runtime:

source ~/.nvm/nvm.sh
nvm alias default 22.22.1
nvm use 22.22.1

After that, a Windows-launched WSL probe resolves:

nodePath:/home/stepanek/.nvm/versions/node/v22.22.1/bin/node
nodeVersion:22.22.1
importMetaMain:true

Suggested product fix: make WSL preflight fail/fallback when the resolved nodePath does not satisfy the server package engine range, even if the node-pty probe succeeds. Also log the selected WSL nodePath and node -v in the backend launch/preflight logs so this is visible without process inspection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions