Skip to content

fix(desktop): WSL backend connects with Docker bridges and slow cold starts - #6129

Open
rehanhaider wants to merge 3 commits into
pingdotgg:mainfrom
rehanhaider:fix/wsl-connection
Open

fix(desktop): WSL backend connects with Docker bridges and slow cold starts#6129
rehanhaider wants to merge 3 commits into
pingdotgg:mainfrom
rehanhaider:fix/wsl-connection

Conversation

@rehanhaider

@rehanhaider rehanhaider commented Aug 11, 2026

Copy link
Copy Markdown

What Changed

  • getDistroIp now prefers the default route’s source address, with hostname -I as the fallback.
  • DEFAULT_BACKEND_READINESS_TIMEOUT increases from 1 to 3 minutes.

Scope: two files, 19 lines, two commits. No tests added—the changes are one shell string and one constant.

Why two commits and not one?

Both commits fix the same user-visible hang, so they ship together.

Both causes the exact same symptoms to the user.

Happy to split if you'd rather take them separately.

Why

On Windows, the desktop can remain on “Connecting to WSL…” when Docker is running inside the distro. The backend starts, listens, and answers readiness checks, but the app targets the wrong address and times out too early. Either bug can cause the hang.

Wrong address

getDistroIp previously selected the first IPv4 address from hostname -I, which lists all bound addresses in interface order. With Docker running, a br-* or docker0 bridge can appear first, directing the renderer to an address Windows cannot route to.

This also breaks mirrored networking. isLocalHostIpv4 in DesktopBackendConfiguration maps the backend to loopback only when the reported address belongs to a Windows interface. A Docker bridge does not match, so mirrored-mode users lose the intended loopback path.

The new command asks the kernel for the default route’s source address using ip -4 route get 192.0.2.1. This avoids interface-name matching and RFC1918 heuristics without adding another spawn. The route source is printed before hostname -I, allowing the existing first-match parser and IPv4 validation to remain unchanged.

hostname -I remains the fallback, so distros without iproute2 or a default route behave as they do today. 192.0.2.1 is reserved by RFC 5737, and this is only a routing-table lookup—no packet is sent.

Readiness timed out too early

Readiness currently receives a single 60-second budget. Loading the server bundle and dependencies across /mnt/c regularly takes longer. When the probe expires, the backend process remains alive but is never marked ready, leaving the splash visible even if startup completes seconds later.

The probe polls every 100 ms and resolves immediately when the backend responds, so increasing the budget does not slow fast launches.

Verification

Verified on Windows 11 with WSL2 mirrored networking and three active Docker bridges—the topology reported in #5211:

hostname -I   ->  172.18.0.1  172.17.0.1  172.19.0.1  192.168.1.5
route source  ->  192.168.1.5

Before the timeout change, with the address fix already applied:

  • Two launches abandoned readiness at exactly 60,000 ms.
  • The backend was listening and answering HTTP 200 at 98 seconds.

After both changes:

  • isLocalHostIpv4 matches 192.168.1.5 to the host Wi-Fi adapter.
  • Readiness targets http://127.0.0.1:.
  • The backend returns HTTP 200 and the desktop connects.

The address fix is evidenced by the route lookup above: hostname -I returns the bridge first, so the previous first-match selection resolves to 172.18.0.1, which Windows cannot route to. Measurements were taken against a dev build (dev:desktop), which also waits on the Vite server, so the 98s figure is not directly a packaged-build number.

Validation:

vp test run apps/desktop/src/wsl/DesktopWslEnvironment.test.ts apps/desktop/src/backend/DesktopBackendManager.test.ts

All 52 tests passed. Typecheck and lint are clean for both changed files.

Related Work

This area is active:

There could be more robustness in the solution but I have preferred simple, tested, and workable solution instead.

Closes #5211
Refs #4535 and #5522.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI, animation, or interaction changes

Note

[!NOTE]

Fix WSL distro IP detection and extend backend readiness timeout

  • Updates getDistroIpImpl in DesktopWslEnvironment.ts to prefer the IPv4 source address of the default route (ip -4 route get 192.0.2.1) before falling back to hostname -I, which is more reliable in multi-interface WSL environments.
  • Increases DEFAULT_BACKEND_READINESS_TIMEOUT in DesktopBackendManager.ts from 1 minute to 3 minutes to accommodate slower WSL startup times.
  • Behavioral Change: the IP returned by getDistroIpImpl may differ in environments with multiple network interfaces.

Macroscope summarized a702228.

getDistroIp took the first IPv4 from `hostname -I`, which prints every
bound address in interface order. A distro running Docker reports its
br-*/docker0 bridges first, so the desktop pointed the renderer at an
address Windows cannot reach and sat on "Connecting to WSL..." until the
readiness budget expired. It also defeated the mirrored-networking check
in DesktopBackendConfiguration, which only collapses to loopback when
the reported address belongs to a Windows interface; a bridge address
never matches.

Print the default route's source address ahead of the `hostname -I`
output so the existing first-match parser picks it up. `hostname -I`
still trails it, so distros without iproute2, or with no default route,
keep today's behaviour. The lookup targets 192.0.2.1 (RFC 5737) and is a
routing-table query, so no packet is sent.

Verified on Windows 11, WSL2 mirrored networking, three Docker bridges:

  hostname -I  ->  172.18.0.1 172.17.0.1 172.19.0.1 192.168.1.5
  route source ->  192.168.1.5

Before, readiness targeted the 172.18.0.1 bridge and never resolved.
After, isLocalHostIpv4 matches 192.168.1.5 against the host adapter and
readiness targets http://127.0.0.1:<port>, which answers 200.

Closes pingdotgg#5211.
The desktop probes backend readiness once with a 60s budget. A WSL
backend loads the server bundle and its dependencies across /mnt/c, so
cold boot regularly exceeds that. When it does the probe gives up, the
run is left alive but never ready, and the app sits on "Connecting to
WSL..." forever even though the backend finishes booting seconds later
and answers 200 on its readiness endpoint.

Measured on Windows 11 with WSL2, two consecutive launches:

  run 1: gave up at 60000ms; backend healthy shortly after
  run 2: gave up at 60000ms; backend listening and answering 200 at 98s

The probe polls every 100ms and resolves the instant the backend
answers, so a larger budget costs nothing when boot is fast.

Refs pingdotgg#4535, pingdotgg#5522.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3bbf43f6-8f9c-455b-8df0-48dd166a6e11

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@macroscopeapp

macroscopeapp Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR modifies WSL connection logic, including how the distro IP is determined. While the intent is to fix connection issues, changes to IP detection on the critical connection path warrant human verification to ensure correctness across different WSL configurations.

You can customize Macroscope's approvability policy. Learn more.

@rehanhaider rehanhaider changed the title Fix/wsl connection fix(desktop): WSL backend connection hangs due to preflight timeout and incorrect IP lookup Aug 11, 2026
@rehanhaider rehanhaider changed the title fix(desktop): WSL backend connection hangs due to preflight timeout and incorrect IP lookup fix(desktop): WSL backend connects with Docker bridges and slow cold starts Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Desktop stuck on "Connecting to WSL" — getDistroIp picks unreachable Docker bridge IP instead of eth0

1 participant