Summary
On Windows with the WSL backend ("Use only WSL"), enabling T3 Connect from the desktop app fails with:
Could not obtain environment link proof: Invalid managed endpoint origin.
The link-proof request goes to the WSL distro's vEthernet address (http://172.x.x.x:3773/api/connect/link-proof), and the server only accepts link-proof requests that are addressed to a loopback host. The CLI path (t3 connect link + restart) works, because the server then requests the proof from http://127.0.0.1:<port> itself.
Version
- T3 Code desktop 0.0.40 on Windows 11
- Backend: WSL 2, Ubuntu, "Use only WSL"
- Server runtime:
~/.t3/wsl-runtime/... (app-managed), listening on 0.0.0.0:3773
Steps to reproduce
- Windows desktop app → Settings → Connections → WSL backend → "Use only WSL".
- Sign in to T3 Connect in the desktop app.
- Enable T3 Connect for "This environment".
Actual behavior
Error toast: Could not obtain environment link proof: Invalid managed endpoint origin.
The failing request is POST http://172.26.x.x:3773/api/connect/link-proof.
Expected behavior
The environment links, or the app uses a loopback URL for this request.
Root cause (v0.0.40 source)
apps/desktop/src/wsl/DesktopWslEnvironment.ts (getDistroIp, around line 97 and 1044): the desktop resolves the distro's hostname -I address and uses it as the WSL backend's httpBaseUrl, deliberately avoiding the flaky localhost forwarding of wslhost.
apps/web/src/cloud/linkEnvironment.ts line 150: the renderer sends origin.localHttpHost = "127.0.0.1", but the request itself is sent to the 172.x base URL.
apps/server/src/cloud/http.ts isAllowedEndpointOrigin (around line 296): rejects the proof when new URL(requestUrl).hostname is not loopback, so every request arriving on the 172.x address fails with Invalid managed endpoint origin.
apps/server/src/server.ts line 717: the server-side path for CLI links calls reconcileDesiredCloudLink("http://127.0.0.1:" + port), which is why the CLI workaround succeeds.
So the two sides disagree: the desktop intentionally talks to the WSL backend via its vEthernet IP, while the link-proof endpoint intentionally accepts only loopback request URLs. Under "Use only WSL" the desktop-initiated link can therefore never succeed.
Workaround (verified)
In the WSL shell:
npx t3@0.0.40 connect login --headless
npx t3@0.0.40 connect link
then restart the desktop app. The app-managed backend provisions the link on startup and the mobile app connects.
Suggestions
- For the WSL backend, send the link-proof request to a loopback URL (e.g.
http://127.0.0.1:<port>) via the desktop main process, or let the desktop orchestrator call reconcileDesiredCloudLink the same way the CLI path does.
- Alternatively, let
isAllowedEndpointOrigin accept the request when the desktop bridge attests the WSL backend address.
- Surface the CLI workaround in the error message.
- Minor: after
t3 connect link, the CLI always suggests npx t3 serve, even when an app-managed server exists. A hint like "or restart the desktop app" would avoid users starting a second server.
Related: #5210 (WSL + T3 Connect not publishing workspaces, likely the same cause), #9056 (WSL backend binds 0.0.0.0).
This report was written by Claude (Anthropic) during a maintenance session on the user's machine, at the user's request. The user reproduced the error and verified the workaround; source references are against tag v0.0.40.
Summary
On Windows with the WSL backend ("Use only WSL"), enabling T3 Connect from the desktop app fails with:
The link-proof request goes to the WSL distro's vEthernet address (
http://172.x.x.x:3773/api/connect/link-proof), and the server only accepts link-proof requests that are addressed to a loopback host. The CLI path (t3 connect link+ restart) works, because the server then requests the proof fromhttp://127.0.0.1:<port>itself.Version
~/.t3/wsl-runtime/...(app-managed), listening on0.0.0.0:3773Steps to reproduce
Actual behavior
Error toast:
Could not obtain environment link proof: Invalid managed endpoint origin.The failing request is
POST http://172.26.x.x:3773/api/connect/link-proof.Expected behavior
The environment links, or the app uses a loopback URL for this request.
Root cause (v0.0.40 source)
apps/desktop/src/wsl/DesktopWslEnvironment.ts(getDistroIp, around line 97 and 1044): the desktop resolves the distro'shostname -Iaddress and uses it as the WSL backend'shttpBaseUrl, deliberately avoiding the flakylocalhostforwarding of wslhost.apps/web/src/cloud/linkEnvironment.tsline 150: the renderer sendsorigin.localHttpHost = "127.0.0.1", but the request itself is sent to the172.xbase URL.apps/server/src/cloud/http.tsisAllowedEndpointOrigin(around line 296): rejects the proof whennew URL(requestUrl).hostnameis not loopback, so every request arriving on the172.xaddress fails withInvalid managed endpoint origin.apps/server/src/server.tsline 717: the server-side path for CLI links callsreconcileDesiredCloudLink("http://127.0.0.1:" + port), which is why the CLI workaround succeeds.So the two sides disagree: the desktop intentionally talks to the WSL backend via its vEthernet IP, while the link-proof endpoint intentionally accepts only loopback request URLs. Under "Use only WSL" the desktop-initiated link can therefore never succeed.
Workaround (verified)
In the WSL shell:
then restart the desktop app. The app-managed backend provisions the link on startup and the mobile app connects.
Suggestions
http://127.0.0.1:<port>) via the desktop main process, or let the desktop orchestrator callreconcileDesiredCloudLinkthe same way the CLI path does.isAllowedEndpointOriginaccept the request when the desktop bridge attests the WSL backend address.t3 connect link, the CLI always suggestsnpx t3 serve, even when an app-managed server exists. A hint like "or restart the desktop app" would avoid users starting a second server.Related: #5210 (WSL + T3 Connect not publishing workspaces, likely the same cause), #9056 (WSL backend binds 0.0.0.0).
This report was written by Claude (Anthropic) during a maintenance session on the user's machine, at the user's request. The user reproduced the error and verified the workaround; source references are against tag v0.0.40.