Repository navigation
CLI silently hangs on stalled HTTPS sockets to api.github.com — no timeout, no log/event output #3371
Description
Describe the bug
The copilot CLI process can silently hang for many minutes (potentially indefinitely) with data permanently backed up in its TCP send buffers to GitHub API endpoints, while producing zero output to either its process log or the session events.jsonl. The user-facing TUI shows no indication that anything is wrong (no spinner change, no error, no "reconnecting…" message); the process simply stops making progress.
The underlying network condition appears to be a stale TCP connection (most likely after a network/route change on a multi-homed host such as VPN/Tailscale on/off, Wi-Fi → Ethernet handoff, etc.). The kernel keeps the socket in ESTAB because there is no TCP keepalive and no application-level write deadline, so the bytes sit in Send-Q forever. The CLI never times out, never retries on a fresh connection, and never surfaces a diagnostic to the user.
Observed signature
$ ss -tnpi | grep "pid=<copilot-pid>"
ESTAB 0 1481886 10.83.27.238:36816 140.82.112.22:443 users:(("MainThread",pid=92622,fd=129))
ESTAB 0 3154 10.83.27.238:40390 140.82.114.21:443 users:(("MainThread",pid=92622,fd=28))
ESTAB 0 2510 10.83.27.238:40396 140.82.114.21:443 users:(("MainThread",pid=92622,fd=39))
ESTAB 0 3042 10.83.27.238:47374 140.82.113.21:443 users:(("MainThread",pid=92622,fd=45))
All peer IPs reverse-resolve to lb-140-82-*-*-iad.github.com (GitHub's IAD load balancers). Notice the non-zero Send-Q values that never drain — these connections are dead from GitHub's perspective but the local kernel still considers them established.
Meanwhile:
$ ls -la --time-style=full-iso ~/.copilot/logs/process-*-92622.log \
~/.copilot/session-state/<sid>/events.jsonl
-rw-r--r-- ... 21:00:43 ... process-1779115412438-92622.log
-rw------- ... 20:48:45 ... <sid>/events.jsonl
…no writes for ~5 and ~17 minutes respectively, while the user is sitting at the prompt with no feedback. The process state is S (sleeping in epoll_wait); from /proc/<pid>/wchan it is parked waiting for EPOLLOUT on the dead sockets.
Affected version
GitHub Copilot CLI 1.0.48
(@github/copilot npm package, Linux x64 binary.)
Steps to reproduce the behavior
Hard to reproduce on demand, but a reliable recipe on a multi-homed Linux host:
- Start a
copilotsession over a network interface that has a default route to GitHub (e.g. a VPN such as Tailscale providing the10.83.27.238address above). - Issue any request that causes the CLI to open HTTPS connections to
api.github.com/*.github.com. - Bring that interface down, change the default route, or otherwise break the path without sending RSTs back to the local kernel (interface down, NAT box reboot, ISP blip, VPN reconnect, suspend/resume).
- Issue another request, or simply wait until the CLI tries to use one of the pooled HTTPS connections.
- The CLI hangs. No log lines, no
events.jsonlentries, no TUI feedback.ss -tnpion the PID shows non-zeroSend-Qto GitHub IPs that never decreases.
It also reproduces "naturally" during ordinary daily use on machines that toggle between VPN/no-VPN or Wi-Fi/Ethernet.
Expected behavior
The CLI should not hang silently on a dead socket. At minimum, one or more of:
- Per-request write/read timeouts on the HTTP client used for GitHub API traffic, so a stalled socket is detected within a bounded time (e.g. tens of seconds) instead of relying on the kernel's default TCP retransmission timeout (which can be 15+ minutes).
- TCP keepalive (
SO_KEEPALIVEwith sensibleTCP_KEEPIDLE/TCP_KEEPINTVL/TCP_KEEPCNT) on long-lived sockets so the kernel itself tears down dead connections faster. - Connection-pool health checks that proactively close and replace sockets that have been idle across a known network change (or just replace on any I/O error / timeout rather than retrying on the same dead FD).
- User-visible feedback in the TUI when an outbound request has been pending longer than a short threshold — even just a "still waiting on api.github.com…" line — so the user can distinguish "the model is thinking" from "we are wedged on a dead socket".
- Either an automatic retry on a fresh connection, or a clear error surfaced to the user with guidance (e.g.
/reconnector similar).
Additional context
- OS: Linux (CachyOS, kernel 7.0.6-1-cachyos, x86_64)
- Node: v26.1.0
- Install:
@github/copilotglobal npm install, binary at/usr/lib/node_modules/@github/copilot/node_modules/@github/copilot-linux-x64/copilot - Terminal / shell: standard pty, bash
- Network: multi-homed — local LAN (
192.168.1.12) + Tailscale (10.83.27.238) + IPv6. The stuck sockets in this incident were all bound to the Tailscale address; concurrently-healthy sockets on the same PID were on IPv6 and on the LAN address.
Diagnostic commands that help confirm the bug
# 1. Stuck send queues on copilot's sockets
ss -tnpi | awk 'NR>1 && /pid=<COPILOT_PID>/ && $3+0>0'
# 2. Process is parked in epoll_wait, not crashed
cat /proc/<COPILOT_PID>/wchan; echo
cat /proc/<COPILOT_PID>/status | grep -E '^(State|Threads)'
# 3. No log/event writes despite the process being "running"
stat -c '%y %n' ~/.copilot/logs/process-*-<COPILOT_PID>.log
stat -c '%y %n' ~/.copilot/session-state/<SID>/events.jsonlWorkaround
sudo ss -K dst <github-ip> dport = 443to forcibly destroy the stuck sockets (requiresCAP_NET_ADMIN).- Or, killing the
copilotprocess and restarting the session. Either way, no in-product recovery is offered.
Related (not duplicates)
- It takes a long time to recover from a network outage #543 — "It takes a long time to recover from a network outage" (general; this issue narrows to the specific socket/timeout signature with concrete diagnostics)
- HTTP MCP servers fail with
TypeError: fetch failedafter idle period — CLI reuses dead pooled TCP connection #3257 — "HTTP MCP servers fail withTypeError: fetch failedafter idle period — CLI reuses dead pooled TCP connection" (same class of bug — stale pooled connection — but for MCP transports rather than the main GitHub API client) - Session hangs ~8 minutes after compaction when prompt cache misses — no timeout or feedback #1614 — "Session hangs ~8 minutes after compaction when prompt cache misses — no timeout or feedback" (different trigger, same lack-of-timeout-and-feedback theme)
Activity
sigsegved commentedon Jun 19, 2026
Corroboration on 1.0.64-0 — same silent HTTPS stall, 3h17m, and it froze an entire multi-hour subagent run
Hitting this exact failure on GitHub Copilot CLI 1.0.64-0 (so it's still present well past 1.0.48), reconstructed from the process log +
events.jsonlafter the fact.Timeline (UTC):
07:54:41.032Z— CLI sends a streaming model request ("stream": true) to the Copilot API ("Start of group: Sending request to the AI model" → "Wire request").07:55–11:11— zero activity. Per-hour count of timestamped process-log entries:06h=9517, 07h=10766, 08h=0, 09h=0, 10h=0, 11h=114. No retry, no timeout, no error, nothing inevents.jsonl, no TUI change — exactly the "parked on a dead socket, zero output" signature described here.11:12:22.255Z— the response for that request (serverRequest-ID 00000-16c57edb-…) is finally logged, 3h 17m 41s after it was sent — and only because the process was being torn down at that moment for an unrelated reason. Left alone it would have waited indefinitely.Aggravating angle not in the original report: the stalled request was issued by a background subagent, not the top-level session. Because the orchestrator was blocked awaiting that subagent, the single dead socket silently froze the entire autonomous run (a multi-hour, 40+ subagent job) — it produced nothing for 3+ hours and had to be manually resumed. So the blast radius isn't just "the user waits at the prompt"; one wedged socket can deadlock a whole subagent tree.
I couldn't capture live
ss -tnpi/Send-Q(diagnosed post-mortem; process already gone), but the log-silence + a single request-id spanning 3h matches the stale-TCP theory here precisely.Strong +1 on the proposed fixes — especially an application-level read/write deadline on model-API traffic and retry on a fresh connection. Please also add a watchdog on subagent model calls: a stalled socket inside a subagent should fail/recover that subagent rather than silently hanging its parent. Even a "still waiting on the model (Ns)…" indicator would have turned a lost night into a 30-second Ctrl-C.
Env: Copilot CLI 1.0.64-0, Node v20.17.0, Microsoft Azure Linux 3.0 (kernel 6.6.x), x86_64, run inside a VS Code Remote integrated terminal.
patniko commentedon Oct 26, 2026
Thanks for the report. We've shipped fixes in this area since this was filed, and we believe this may now be resolved. Could you retest on the latest release (Copilot CLI v1.0.103) and let us know whether you still see it? If we don't hear back in a couple of weeks, we may close this issue — you can always reopen it.
Triaged as part of a Copilot SDK backlog review, with help from GitHub Copilot.