Skip to content

Open in editor hangs forever when the server runs inside a Docker container reached over SSH #8278

Open

Description

@oc-andrey-zaharov

What happened

Open in editor doesn't work. My client is Cursor on a Mac, but the T3 server runs inside a VM-hosted Docker container that I reach with gcloud compute ssh --tunnel-through-iap into the VM followed by docker exec -it t3 bash. When I click Open in Cursor, Cursor launches on my Mac and shows "connecting" but the connection runs forever and never opens the workspace.

Diagnosis

The environment is classified as a remote SSH environment, so open-in-editor takes the remote-links path and hands the OS a deep link instead of exec'ing an editor on the server host:

cursor://vscode-remote/ssh-remote+<host><container-path>

built by buildRemoteOpenUrl (packages/contracts/src/editor.ts). This is confirmed by the server traces containing no shell.openInEditor RPC span for the attempts — in remote-links mode the deep link fires entirely client-side (openRemoteEditorUrl in apps/web/src/remoteOpen.ts) and never reaches the server.

The deep link can't ever connect, because ssh-remote+<host> can only address an SSH host, while the workspace lives inside a Docker container reachable only via ssh <VM> && docker exec:

  • Cursor/VS Code Remote-SSH connects to the VM, whose filesystem does not contain the container path (/workspace/repos/<project>), and
  • Remote-SSH cannot perform the docker exec hop, so it stalls bringing up the remote server / never lands on the right filesystem.

There is no ssh alias or advertised target that resolveRemoteOpenState / RemoteOpenTargets could carry that would open a containerized backend, so both open-in-editor strategies are dead ends for this topology:

  • remote-links → generates a link to the VM, which hangs (this report).
  • local-exec → would exec the editor inside the container, which has no editor on PATH, no DISPLAY, and is the wrong machine anyway.

RemoteOpenTargets.resolveTargets() (apps/server/src/environment/RemoteOpenTargets.ts) also advertises nothing here (no sshd on :22, no Tailscale), so even the direct-remote path has no route — but the failure the user sees is the ssh-alias deep link hanging, not the "No SSH route" dead-end.

Root gap: open-in-editor has no notion of a backend that lives inside a container behind an SSH host. A vscode-remote link would need the attached-container/dev-containers authority (…/attached-container+<hex>…) or an equivalent, not ssh-remote+<host>.

Steps to reproduce

  1. Run the T3 server inside a Docker container on a remote VM (npx t3 serve inside docker exec -it <container> bash); the VM is reached over SSH (here via gcloud compute ssh --tunnel-through-iap).
  2. Connect the T3 desktop app on a Mac to that server as a remote/SSH environment; have Cursor (or any Remote-SSH-capable editor) installed locally.
  3. Open a thread in a project whose workspace is a container path (e.g. /workspace/repos/<project>).
  4. Click Open-in-editor → Cursor.

Expected: Cursor opens the workspace on the Mac.
Actual: Cursor launches and hangs on "connecting" indefinitely; the workspace never opens. No shell.openInEditor span appears in server.trace.ndjson.

Version

0.0.34 (tag v0.0.34, latest stable)

Environment

Client: macOS, T3 desktop app (Electron), Cursor installed locally. Server: T3 0.0.34 in a Linux x64 Docker container (Node v24.19.0) on a GCP VM, reached via gcloud compute ssh --tunnel-through-iap + docker exec. Server bound to 127.0.0.1:8787.

Evidence

# Server host (the container): none of the routes open-in-editor relies on exist
$ ss -ltnp | grep ':22'        # -> no sshd
(no output)
$ command -v tailscale          # -> absent
$ command -v code cursor codium code-insiders zed   # -> none installed
$ ls /.dockerenv                # -> present (inside docker)
$ echo "$DISPLAY"               # -> empty (headless)

# RemoteOpenTargets therefore advertises nothing (RemoteOpenTargets.ts):
#   if (!sshdListening) return [];

# Clients on record (auth_sessions; credential columns omitted):
#   desktop  MacIntel  Electron   bearer-access-token   <- the failing client
#   desktop  macOS     Chrome     browser-session-cookie
#   mobile   iOS       Safari     browser-session-cookie

# Workspace roots are container paths (projection_projects):
#   /workspace/repos/<project>
#   /root/repos

# No server-side editor launch for the click:
$ grep -c 'shell.openInEditor' server.trace.ndjson*   # -> 0
#   (remote-links deep link fires client-side; never hits the server RPC)

Related issues

#7530 — same open-in-editor local-vs-remote subsystem, but a different failure: there a same-machine browser on a LAN IP is misclassified as remote and dead-ends at a disabled "No SSH route". This report is the opposite end — the environment is correctly remote, a deep link is generated, but ssh-remote+<host> cannot traverse into a Docker container, so it hangs. Not a duplicate.

Fix applied or workaround

Nothing was written to the machine (no DB writes, no source patches). Workaround: use Cursor's Dev Containers: Attach to Running Container — Remote-SSH into the VM, then attach to the t3 container and open the workspace folder. This is the only flow that crosses the docker exec boundary; T3's button cannot drive it.

Filed by

claude (Opus 4.8) via t3 triage

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions