Worktree bootstrap fetch hangs for the full 30s timeout when a GUI SSH agent is waiting on key authorization
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
Description
What happened
I've noticed the last few days that the mobile app fails to actually start a thread on my tailscale machines. It only happens when I am trying to start the thread with a new worktree. The remote machine will eventually get the thread/message, but it will not start the agent work. I just created a new thread without a worktree and it worked fine.
The error shown on mobile:
COULD NOT START TASK Git command failed in GitVcsDriver.fetchRemote: Git command timed out. Your prompt was kept in the project draft.
Diagnosis
Starting a thread with New worktree + Start from origin runs fetchRemote in ws.ts, which calls GitVcsDriver.fetchRemote with no timeoutMs and so inherits DEFAULT_TIMEOUT_MS = 30_000.
When origin is an SSH remote and the user's agent is a GUI agent that requires authorization for the requesting application (1Password, Secretive, Yubikey touch), the agent raises an approval prompt. When the request comes from a background app, that prompt is a passive tray notification rather than a focused window. ssh blocks on the agent socket, git makes no progress, and the driver kills it at 30s reporting Git command timed out.
STATUS_UPSTREAM_REFRESH_ENV sets GCM_INTERACTIVE=never, GIT_ASKPASS="", GIT_TERMINAL_PROMPT=0, SSH_ASKPASS="" and SSH_ASKPASS_REQUIRE=never specifically to stop auth from hanging, and GitVcsDriverCore.test.ts asserts all five reach git. The guard is incomplete: those variables govern terminal and askpass prompting only, and have no effect on an agent prompting over SSH_AUTH_SOCK. The test stubs GIT_SSH with a wrapper that exit 1s immediately, so it verifies the variables are set but never exercises an agent that blocks.
Note that IdentityAgent in ~/.ssh/config overrides SSH_AUTH_SOCK, so the agent is reached regardless of what environment the server process inherits. This is not an environment-propagation problem.
Three things make this hard to self-diagnose:
- The error says
Git command timed out, pointing at the network or the repo, when the real cause is a pending key authorization. - The 30s deadline expires before the agent's own prompt deadline (60s for 1Password), so a user who notices the tray icon still has under 30s to approve.
- It presents as intermittent. It fails when nobody is at the machine to approve, which is exactly when the mobile app is used.
This is orthogonal to repo size. The repo here is 18 refs, 3.5M .git, 1 pack, and fetches in ~1.1s once authorized.
Note for #10943: timeoutMs: null converts the 30s timeout into a stall lasting until the agent's own prompt timeout, after which git fails with a genuine auth error. Better message, worse latency. A targeted fix would detect an outstanding agent handshake with no fetch progress and surface an authorization-specific error, rather than tuning the deadline.
Steps to reproduce
- Configure a GUI SSH agent that requires per-application approval, and point
IdentityAgentat it in~/.ssh/config. - Give a project an SSH
origin(git@github.com:<user>/<repo>.git). - Ensure the agent has no standing authorization for the requesting process, and leave the machine so no prompt is approved.
- From the mobile app, start a thread on that project with New worktree and Start from origin.
- After 30s the thread fails with
Git command failed in GitVcsDriver.fetchRemote: Git command timed out.No thread row is persisted and the prompt returns to the project draft.
A thread on the same project without a worktree succeeds, because no network fetch occurs.
Version
0.0.41-nightly.20260914.1707 (desktop Nightly app). Contains #11633.
Environment
macOS 27.0.0 arm64, Node v24.18.1, desktop Nightly app as server, mobile app as originating surface, 1Password 8 as SSH agent.
Evidence
T3 Code trace spans (UTC):
ws.rpc.orchestration.dispatchCommand 30101ms Failure
fetchRemote 30004ms Failure
GitVcsDriver.fetchRemote 30004ms Failure git.args_count=3
runGitCommand 30001ms Interrupted
runGitCommand started 15:38:19.061, killed 15:38:49.061
1Password agent log, same window (UTC):
15:38:19.548 op-ssh-agent: Notifying user through tray icon that they
have a background prompt waiting
15:39:19.400 op-ssh-agent: ssh authorization prompt timed out
Second occurrence, same pattern:
16:14:51 background prompt waiting
16:15:50 ssh authorization prompt timed out
Direct reproduction outside the app, agent authorization left unanswered,
running git under the driver's exact environment:
git ls-remote git@github.com:<user>/<repo>.git HEAD
-> 60.86s, then:
sign_and_send_pubkey: signing failed for ED25519 ".../id_ed25519"
from agent: communication with agent failed
Agent log: ssh authorization prompt timed out
The runGitCommand child span confirms git was spawned and ran the full
budget before Effect interrupted it. The same fetch completes in ~1.1s
once the agent request is authorized.
Related issues
#10916 is the same symptom caused by a genuinely slow fetch on a large repo; this fails on a 3.5M repo whose fetch takes ~1.1s, so the cause is distinct. #10179 is the inverse shape, SSH_AUTH_SOCK missing entirely under OrbStack systemd, where the agent is unreachable rather than prompting. #1190 (closed) covers repeated unlock prompts in the UI, not a blocked fetch.
Fix applied or workaround
Moving the project's origin to HTTPS with the gh auth git-credential helper removes the SSH agent from the path. Verified on the affected machine, running git under the driver's exact environment with GIT_SSH_COMMAND=/bin/false and SSH_AUTH_SOCK unset so no SSH fallback is possible:
public repo, git fetch --quiet origin -> exit 0, 0.49s
private repo, git ls-remote HEAD -> ref returned, 0.66s
SSH control, same environment -> 60.86s, agent failure
The credential helper authenticates correctly despite GIT_ASKPASS="" and GIT_TERMINAL_PROMPT=0. Disabling per-request approval for the SSH key is the alternative if SSH remotes must be kept.
Filed by
claude (opus-5) via t3 triage
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with fetchRemote in ws.ts and the timeout handling in GitVcsDriver, then read GitVcsDriverCore.test.ts and its existing environment assertions. Reproduce the SSH-agent authorization stall under the documented environment and add coverage for the stalled handshake. Done means the fetch reports an authorization-specific failure instead of the generic 30-second timeout.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git, typescript
- Domain
- backend, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100