[Bug]: WSL-only mode stuck on "Connecting to WSL..." forever when the WSL backend keeps crashing on startup#14393

openedSep 30, 2026byNNightHunter30

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. On Windows, go to Settings > Connections, set the WSL backend to a distro (Ubuntu-22.04 here) and pick "Use only WSL". The app relaunches.
  2. The WSL backend fails to start. For me it crashed on every start, see the logs below. The bundled runtime needed libatomic.so.1, which my Ubuntu 22.04 didn't have. So it fell back to the mounted server tree, and that died with Cannot find module '@yuuang/ffi-rs-linux-x64-gnu'.
  3. The app sits on "Connecting to WSL..." and never gets past it.

You can also hit it by making the backend unreachable instead of crashing, e.g. sudo iptables -I INPUT -p tcp --dport <port> -j DROP inside the distro before launching.

Expected behavior

If the WSL backend can't come up, the app should show an error and fall back to the Windows backend for that launch, like it already does when the WSL preflight fails. At minimum it should get me to a window where I can turn WSL-only off.

Actual behavior

The splash never closes. It has no buttons, and clicking the taskbar icon just brings the splash back, so there's no way to reach Settings. The logs show the backend exiting with code 1 and being restarted every ~10s with no limit. One session had 62 restarts in 13 minutes before I killed it. The only way out was ending it in Task Manager and setting "wslOnly": false in desktop-settings.json by hand.

From reading the code on main (0fcd5f90): the splash only closes once the primary backend reports ready. WSL preflight failures fall back to Windows, but once preflight passes there's no limit:

I have a small fix: after 3 consecutive startup failures in wsl-only mode, show an error and use the existing in-memory Windows fallback for that launch. The desktop tests pass with it, and the new test hangs without it. I'll open a PR and link it here.

Probably related: #3709, #4535, #5967, #13738

Impact

Blocks work completely

Version or commit

0.0.44 (Windows desktop)

Environment

Windows 10 22H2 (19045.6466), WSL 3.0.1.0 (NAT), Ubuntu 22.04

Logs or stack traces

shell
1# desktop.trace.ndjson, repeats every ~10s
2wslPreflight: "Could not stage the WSL runtime; launching from the mounted server tree instead." reason: "WSL runtime archive does not contain a working t3 executable"
3probeReadiness: Interrupted
4scheduleRestartFiber: "backend exited unexpectedly; restart scheduled" reason: "code=1"
5
6# server-child.log, every run
7Error: Cannot find module '@yuuang/ffi-rs-linux-x64-gnu'
8Require stack:
9- /mnt/c/Users/<me>/.t3/userdata/wsl-server-tree/0.0.44/node_modules/ffi-rs/index.js
10code: 'MODULE_NOT_FOUND'
11
12# running the bundled runtime by hand inside the distro
13$ ./t3 --version
14./t3: error while loading shared libraries: libatomic.so.1: cannot open shared object file: No such file or directory

Screenshots, recordings, or supporting files

No response

Workaround

Kill T3 Code in Task Manager, set "wslOnly": false in %USERPROFILE%\.t3\userdata\desktop-settings.json, and relaunch.

In my case, sudo apt-get install -y libatomic1 in the distro also fixed the crash itself.

Triage

Confirmed on current main. In wsl-only mode, the "Connecting to WSL…" splash stays up until the primary backend reports ready, and it has no controls, so a backend that never becomes ready leaves you no way back to Settings. Preflight failures are already capped (MAX_PREFLIGHT_FAILURE_ATTEMPTS), and handlePrimaryPreflightFailure falls back to Windows. A backend that passes preflight and then dies isn't capped: scheduleRestart only limits the delay (500ms, doubling, up to 10s), never the number of attempts, which matches the ~10s restart loop. A process that stays up but never answers is the other loop: probeReadiness keeps retrying on a 60s budget for as long as the child is alive.

The two crashes in your log explain why preflight passes and the process still exits:

  1. The staged runtime's readiness check runs t3 --version with stderr discarded (runtime_entry_runs). Any dynamic-linker failure, including the missing libatomic.so.1 on Ubuntu 22.04, gets reported as "WSL runtime archive does not contain a working t3 executable", and the install falls through to the mounted server tree. That fits libatomic1 making ./t3 --version work. The archive can be intact while the binary still can't run on that distro, and the linker error never reaches desktop.trace.ndjson.

  2. The mounted tree is the Windows server sidecar (server.asar extracted under wsl-server-tree), installed for win32, so ffi-rs's optional @yuuang/ffi-rs-linux-x64-gnu binding isn't in it. Server startup requires @ff-labs/fff-node from WorkspaceSearchIndex.ts, which loads ffi-rs, and Linux Node throws MODULE_NOT_FOUND. The mounted-tree preflight only requires node-pty (whose Linux prebuild ships inside that package), so preflight reports ready and the exit is treated as an unexpected crash rather than a preflight failure. The code comment saying this fallback is recoverable doesn't hold for this tree.

This isn't a duplicate of open issue #3709 (login-shell Node older than 22.16 exits 0 before binding), closed issue #4535 (slow /mnt/c boot; the readiness probe now retries while the process is alive), closed issue #5967 (same splash, but no logs), or open issue #13738 (dual mode with a healthy backend that Windows can't reach at the NAT address). Those can show the same splash, but the lockout here comes from an uncapped failure after preflight in wsl-only mode.

An in-memory Windows fallback after repeated startup failures is the right recovery. It has the same shape as the non-fatal preflight path (applyWslWindowsFallbackInMemory), so wslOnly stays set for the next launch. It needs to cover both loops: exits before ready, and a live process whose readiness probes keep failing (the iptables case). That fallback won't make the staged runtime run without libatomic.so.1, and it won't make the Windows sidecar load ffi-rs on Linux. Those are separate fixes.

Synced from GitHub

Same crash loop here on T3 Code 0.0.46-nightly.20261007.2761, Windows 11, WSL Ubuntu 22.04.1, Node v24.21.0 via nvm. libatomic1 was not installed.

One more data point for the fallback path: ffi-rs is not the only native package with missing Linux binaries in wsl-server-tree. The tree only ships the win32 variants of:

  • @yuuang/ffi-rs (missing @yuuang/ffi-rs-linux-x64-gnu@1.3.7)
  • @napi-rs/keyring (missing @napi-rs/keyring-linux-x64-gnu@1.3.0)
  • @ff-labs/fff-node (missing @ff-labs/fff-bin-linux-x64-gnu@0.9.4)

node-pty is fine since it bundles prebuilds for all platforms.

After unpacking those three into wsl-server-tree/<version>/node_modules, all modules load in WSL Node and the backend starts. So a fix for the fallback tree needs to include all three Linux packages (and probably the -musl variants for Alpine distros), not just ffi-rs.

Synced from GitHub

Same symptom here on T3 Code 0.0.45 (Windows 11, WSL 2.6.1, Debian 12 bookworm). Root cause was a missing libatomic1 package in the distro. Posting the full chain in case it helps others.

Symptoms

  • Stuck on "Connecting to WSL…" forever
  • server-child.log loops on: Error: Cannot find module '@yuuang/ffi-rs-linux-x64-gnu' (require stack in wsl-server-tree/0.0.45/node_modules/ffi-rs/index.js)
  • desktop.trace.ndjson: Could not stage the WSL runtime; launching from the mounted server tree instead. with reason WSL runtime installation failed (exit 1): WSL runtime archive does not contain a working t3 executable

What's actually happening

  1. The staged runtime binary ~/.t3/wsl-runtime/sha256-…/t3 is dynamically linked against libatomic.so.1 (visible in ldd). The default Debian 12 WSL image doesn't include libatomic1, so the binary can't start and staging fails.
  2. T3 then falls back to the mounted Windows server tree (%USERPROFILE%\.t3\userdata\wsl-server-tree\<version>), which only contains the win32 native bindings (@yuuang/ffi-rs-win32-*), so the backend crashes on the missing Linux binding and gets restarted in a loop.

The Node version was fine here (v24.21.0 was selected), so this is not the #3611 problem.

Fix

bash
1sudo apt-get update
2sudo apt-get install -y libatomic1

Then quit T3 Code completely (including the tray icon) and start it again. You can check that the staged runtime works with:

bash
1~/.t3/wsl-runtime/sha256-*/t3 --version

Gotcha: if apt refuses with "Unmet dependencies" because of some other broken package (in my case a half-installed google-chrome-stable), apt won't install anything until that's resolved. Run sudo apt --fix-broken install or remove the broken package first.

Suggestion: "archive does not contain a working t3 executable" hides the real loader error. Surfacing the stderr of the probe (e.g. error while loading shared libraries: libatomic.so.1) or checking for libatomic.so.1 during preflight would make this self-explanatory.

Synced from GitHub

It is not possible to use t3 code in WSL: the process of connecting to WSL never completes. This error persists even if you completely uninstall t3 code and reinstall it.

Image
Synced from GitHub

https://github.com/pingdotgg/t3code/issues/14393#issuecomment-6081108422

almost same issue, but on Surface Laptop, which runs on ARM. It keeps looping back to this:

1Cannot find module '@yuuang/ffi-rs-linux-arm64-gnu'\nRequire stack:\n- /mnt/c/Users/XXX/.t3/userdata/wsl-server-tree/0.1.1/node_modules/ffi-rs/index.js

but I can't install the package obviously, it should have been @yuuang/ffi-rs-win32-x64-msvc

Synced from GitHub

Same symptom here on T3 Code 0.0.45 (Windows 11, WSL 2.6.1, Debian 12 bookworm). Root cause was a missing libatomic1 package in the distro. Posting the full chain in case it helps others.

Symptoms

  • Stuck on "Connecting to WSL…" forever
  • server-child.log loops on: Error: Cannot find module '@yuuang/ffi-rs-linux-x64-gnu' (require stack in wsl-server-tree/0.0.45/node_modules/ffi-rs/index.js)
  • desktop.trace.ndjson: Could not stage the WSL runtime; launching from the mounted server tree instead. with reason WSL runtime installation failed (exit 1): WSL runtime archive does not contain a working t3 executable

What's actually happening

  1. The staged runtime binary ~/.t3/wsl-runtime/sha256-…/t3 is dynamically linked against libatomic.so.1 (visible in ldd). The default Debian 12 WSL image doesn't include libatomic1, so the binary can't start and staging fails.
  2. T3 then falls back to the mounted Windows server tree (%USERPROFILE%\.t3\userdata\wsl-server-tree\<version>), which only contains the win32 native bindings (@yuuang/ffi-rs-win32-*), so the backend crashes on the missing Linux binding and gets restarted in a loop.

The Node version was fine here (v24.21.0 was selected), so this is not the #3611 problem.

Fix

sudo apt-get update sudo apt-get install -y libatomic1 Then quit T3 Code completely (including the tray icon) and start it again. You can check that the staged runtime works with:

~/.t3/wsl-runtime/sha256-*/t3 --version Gotcha: if apt refuses with "Unmet dependencies" because of some other broken package (in my case a half-installed google-chrome-stable), apt won't install anything until that's resolved. Run sudo apt --fix-broken install or remove the broken package first.

Suggestion: "archive does not contain a working t3 executable" hides the real loader error. Surfacing the stderr of the probe (e.g. error while loading shared libraries: libatomic.so.1) or checking for libatomic.so.1 during preflight would make this self-explanatory.

That didn't help.

I already had the libatomic1 package installed.

Image Image
Synced from GitHub

Same symptom here on T3 Code 0.0.45 (Windows 11, WSL 2.6.1, Debian 12 bookworm). Root cause was a missing libatomic1 package in the distro. Posting the full chain in case it helps others. Symptoms

  • Stuck on "Connecting to WSL…" forever
  • server-child.log loops on: Error: Cannot find module '@yuuang/ffi-rs-linux-x64-gnu' (require stack in wsl-server-tree/0.0.45/node_modules/ffi-rs/index.js)
  • desktop.trace.ndjson: Could not stage the WSL runtime; launching from the mounted server tree instead. with reason WSL runtime installation failed (exit 1): WSL runtime archive does not contain a working t3 executable

What's actually happening

  1. The staged runtime binary ~/.t3/wsl-runtime/sha256-…/t3 is dynamically linked against libatomic.so.1 (visible in ldd). The default Debian 12 WSL image doesn't include libatomic1, so the binary can't start and staging fails.
  2. T3 then falls back to the mounted Windows server tree (%USERPROFILE%\.t3\userdata\wsl-server-tree\<version>), which only contains the win32 native bindings (@yuuang/ffi-rs-win32-*), so the backend crashes on the missing Linux binding and gets restarted in a loop.

The Node version was fine here (v24.21.0 was selected), so this is not the #3611 problem. Fix sudo apt-get update sudo apt-get install -y libatomic1 Then quit T3 Code completely (including the tray icon) and start it again. You can check that the staged runtime works with: ~/.t3/wsl-runtime/sha256-*/t3 --version Gotcha: if apt refuses with "Unmet dependencies" because of some other broken package (in my case a half-installed google-chrome-stable), apt won't install anything until that's resolved. Run sudo apt --fix-broken install or remove the broken package first. Suggestion: "archive does not contain a working t3 executable" hides the real loader error. Surfacing the stderr of the probe (e.g. error while loading shared libraries: libatomic.so.1) or checking for libatomic.so.1 during preflight would make this self-explanatory.

That didn't help.

I already had the libatomic1 package installed.

Image Image

Clarification.

My work environment:

  • Windows 11 Pro, 26H2, 26300.9711
  • WSL: Ubuntu 26.04.1 LTS, 6.18.54.1-microsoft-standard-WSL2

I used to run t3 code in a Windows environment. Then I chose WSL as my backend, and since then t3 code hasn't worked even in Windows: when I launch the app, a small window appears that says "Connecting to WSL...". This process never completes—the app doesn't launch even in a Windows environment.

Synced from GitHub

Same symptom here on T3 Code 0.0.45 (Windows 11, WSL 2.6.1, Debian 12 bookworm). Root cause was a missing libatomic1 package in the distro. Posting the full chain in case it helps others.

Symptoms

  • Stuck on "Connecting to WSL…" forever
  • server-child.log loops on: Error: Cannot find module '@yuuang/ffi-rs-linux-x64-gnu' (require stack in wsl-server-tree/0.0.45/node_modules/ffi-rs/index.js)
  • desktop.trace.ndjson: Could not stage the WSL runtime; launching from the mounted server tree instead. with reason WSL runtime installation failed (exit 1): WSL runtime archive does not contain a working t3 executable

What's actually happening

  1. The staged runtime binary ~/.t3/wsl-runtime/sha256-…/t3 is dynamically linked against libatomic.so.1 (visible in ldd). The default Debian 12 WSL image doesn't include libatomic1, so the binary can't start and staging fails.
  2. T3 then falls back to the mounted Windows server tree (%USERPROFILE%\.t3\userdata\wsl-server-tree\<version>), which only contains the win32 native bindings (@yuuang/ffi-rs-win32-*), so the backend crashes on the missing Linux binding and gets restarted in a loop.

The Node version was fine here (v24.21.0 was selected), so this is not the #3611 problem.

Fix

sudo apt-get update sudo apt-get install -y libatomic1 Then quit T3 Code completely (including the tray icon) and start it again. You can check that the staged runtime works with:

~/.t3/wsl-runtime/sha256-*/t3 --version Gotcha: if apt refuses with "Unmet dependencies" because of some other broken package (in my case a half-installed google-chrome-stable), apt won't install anything until that's resolved. Run sudo apt --fix-broken install or remove the broken package first.

Suggestion: "archive does not contain a working t3 executable" hides the real loader error. Surfacing the stderr of the probe (e.g. error while loading shared libraries: libatomic.so.1) or checking for libatomic.so.1 during preflight would make this self-explanatory.

The fix worked for me. Thanks!

Synced from GitHub

Still reproducible on 0.1.2 (Windows 11 26200, WSL Ubuntu 24.04.3 x86_64, system Node v22.23.4). The default Ubuntu 24.04 WSL image here didn't have libatomic1, so this hits a stock install, not just 22.04/Debian.

Since #21658 the real reason does reach desktop.trace.ndjson, but only there. The UI still shows "Connecting to WSL (Ubuntu)" indefinitely:

shell
1# desktop.trace.ndjson, every attempt
2"Could not stage the WSL runtime; launching from the mounted server tree instead."
3reason: "WSL runtime installation failed (exit 1): .../t3: error while loading shared libraries: libatomic.so.1: cannot open shared object file: No such file or directory
4WSL runtime archive does not contain a working t3 executable"
5
6# server-child-wsl_Ubuntu.log, every restart (exit code=1)
7Error: Cannot find module '@yuuang/ffi-rs-linux-x64-gnu'
8- /mnt/c/Users/<me>/.t3/userdata/wsl-server-tree/0.1.2/node_modules/ffi-rs/index.js

Restarts after preflight are still uncapped on current main (242d00cd34). The exit goes through scheduleRestart in apps/desktop/src/backend/DesktopBackendManager.ts with only the delay capped.

Workaround confirmed: sudo apt-get update && sudo apt-get install -y libatomic1 in the distro, then restart T3 Code. The staged runtime then installs and starts, and the legacy wsl-server-tree is cleaned up.