Skip to content

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

Open
macodev00/t3code
#87

Description

@NightHunter30

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 (0fcd5f9): 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

# desktop.trace.ndjson, repeats every ~10s
wslPreflight: "Could not stage the WSL runtime; launching from the mounted server tree instead." reason: "WSL runtime archive does not contain a working t3 executable"
probeReadiness: Interrupted
scheduleRestartFiber: "backend exited unexpectedly; restart scheduled" reason: "code=1"

# server-child.log, every run
Error: Cannot find module '@yuuang/ffi-rs-linux-x64-gnu'
Require stack:
- /mnt/c/Users/<me>/.t3/userdata/wsl-server-tree/0.0.44/node_modules/ffi-rs/index.js
code: 'MODULE_NOT_FOUND'

# running the bundled runtime by hand inside the distro
$ ./t3 --version
./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.

Activity

  1. added
    bugSomething is broken or behaving incorrectly.
    needs-triageIssue needs maintainer review and initial categorization.
    on Sep 30, 2026
  2. juliusmarminge commented on Sep 30, 2026

    @juliusmarminge
    Member

    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.

  3. added
    acceptedfeature request accepted
    via-triageFiled through npx t3 triage
    and removed
    needs-triageIssue needs maintainer review and initial categorization.
    on Sep 30, 2026
  4. HolzmannSpace commented on Oct 7, 2026

    @HolzmannSpace

    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.

  5. AltinEtemaj commented on Oct 9, 2026

    @AltinEtemaj

    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.

  6. haosmos commented on Oct 21, 2026

    @haosmos

    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
  7. AltinEtemaj commented on Oct 21, 2026

    @AltinEtemaj

    11. 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

    #14393 (comment)

  8. thclaude commented on Oct 21, 2026

    @thclaude

    #14393 (comment)

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

    Cannot 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

  9. haosmos commented on Oct 21, 2026

    @haosmos

    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
  10. added
    needs more infoInitial triage showed no bug. Awaiting more info
    and removed
    needs more infoInitial triage showed no bug. Awaiting more info
    on Oct 22, 2026
  11. haosmos commented on Oct 22, 2026

    @haosmos

    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.

  12. arsh1198 commented on Oct 22, 2026

    @arsh1198

    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!

  13. vkhamianok commented on Oct 25, 2026

    @vkhamianok

    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:

    # desktop.trace.ndjson, every attempt
    "Could not stage the WSL runtime; launching from the mounted server tree instead."
    reason: "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
    WSL runtime archive does not contain a working t3 executable"
    
    # server-child-wsl_Ubuntu.log, every restart (exit code=1)
    Error: Cannot find module '@yuuang/ffi-rs-linux-x64-gnu'
    - /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 (242d00c). 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.

  14. MaxFabian25 commented on Nov 10, 2026

    @MaxFabian25

    Another way into the mounted-tree fallback, on x64 with libatomic1 installed: a busy distro. The staged runtime is installed and works, but its preflight probe times out, so the desktop falls back to the mounted server tree. That tree ships only the win32 ffi-rs bindings, so the backend dies.

    Environment

    • Windows 11 (10.0.26200), WSL 3.0.3.0, Ubuntu 24.04.5 x86_64, Node v26.13.0, libatomic1 14.2.0 installed
    • T3 Code (Nightly) desktop 0.1.9-nightly.20261110.4452, wslOnly: true
    • Load average about 20 inside the distro at the time, from unrelated test jobs

    Sequence (UTC, from desktop.trace.ndjson and server-child.log)

    1. 08:06:34, 08:08:30 and 08:09:01: desktop.backendConfiguration.wslPreflight logged The staged WSL runtime did not start; retrying from the mounted server tree. with reason WSL backend preflight timed out while probing for the staged runtime. WSL may be slow to start; retry, or check that the distro is healthy. The staged runtime for this version (~/.t3/wsl-runtime/sha256-533f…/t3) was already installed, and had run at 07:52 and 08:01. Those two runs exited with code 78 only because a background service held the T3 home, which was stopped before 08:06.
    2. 08:06:34 to 08:07:54: the desktop extracted server.asar to C:\Users\<user>\.t3\userdata\wsl-server-tree\0.1.9-nightly.20261110.4452.
    3. 08:10:12: the backend started from that tree and exited with code 1:
      Error: Cannot find module '@yuuang/ffi-rs-linux-x64-gnu'
      Require stack:
      - /mnt/c/Users/<user>/.t3/userdata/wsl-server-tree/0.1.9-nightly.20261110.4452/node_modules/ffi-rs/index.js
      
      node_modules/@yuuang in the tree holds only ffi-rs-win32-ia32-msvc and ffi-rs-win32-x64-msvc.
    4. 08:10:13: primary backend failing to start, then startup recovery window shown. So on this build the app no longer stays on the splash.
    5. 08:12:33: Could not stage the WSL runtime; launching from the mounted server tree instead. with reason WSL runtime installation timed out. Check that the distro has free disk space, then retry. The distro had 437 GB free, and the Windows drive holding its virtual disk had 23 GB.
    6. 08:13: I quit and reopened the app. At 08:14:19 the staged runtime started, the token request returned 200 and the main window opened. I changed nothing in between.

    So a timeout on a slow but healthy distro sends the app to a fallback that can't start on any Linux architecture, because the tree has no Linux bindings for ffi-rs (nor, as noted above, for @napi-rs/keyring or @ff-labs/fff-node). In this case, retrying the staged runtime with a longer timeout would have worked, while the fallback never could.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions