Description
Does this issue occur when all extensions are disabled?: Yes
Environment:
VS Code Version: 1.100.3
Remote-SSH Extension Version: v0.120.0
Remote Environment: Docker Container
Docker Host OS: Linux (NAS Synology)
Docker Version: 24.0.2, build 610b8d0
Client OS: Windows 11
Remote OS:
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)" NAME="Debian GNU/Linux" VERSION_ID="12" VERSION="12 (bookworm)" VERSION_CODENAME=bookworm ID=debian
Problem Description
When connected to a Debian 12 Docker container via the Remote-SSH extension, extensions that require external network access, most notably GitHub Copilot, fail to activate.
The primary symptom is a consistent ConnectTimeoutError in the extension logs when attempting to connect to api.github.com and api.individual.githubcopilot.com. This occurs despite the container having full, verifiable network connectivity to these exact endpoints from the command line.
User-facing error: "Copilot took too long to get ready. Please review the guidance in the Chat view."
GitHub Copilot Chat log:
[error] TypeError: fetch failed
at node:internal/deps/undici/undici:13502:13
...
ConnectTimeoutError: Connect Timeout Error (attempted address: api.github.com:443, timeout: 10000ms)
at onConnectTimeout (.../undici/lib/core/connect.js:237:24)
at Immediate._onImmediate (.../undici/lib/core/connect.js:206:11)
at processImmediate (node:internal/timers:483:21): Failed to get copilot token
[error] GitHub Copilot could not connect to server. Extension activation failed: "fetch failed"
Extensive Diagnostic Analysis
This issue has been subject to a deep and systematic debugging process, ruling out all common configuration and environment issues. The evidence strongly suggests a low-level bug in how the VSCode Server's extensionHost process handles its networking event loop.
-
Network Connectivity is Valid:
Standard tools within the container can successfully connect to the GitHub endpoints without any issue.curl -4 https://api.github.com -> SUCCESS
curl -4 https://api.individual.githubcopilot.com -> SUCCESS
A minimal Node.js script using fetch also works perfectly when run from the container's shell. -
DNS Resolution is Not the Cause:
The issue persists even when DNS resolution is completely bypassed by mapping the relevant domains to their correct IPv4 addresses in the container's /etc/hosts file. When this is done, no DNS requests are seen on the local network's DNS server, confirming /etc/hosts is being read, yet the timeout still occurs. -
IPv6 is Not the Cause:
While initial investigation pointed towards an IPv6 issue (curl -6 fails, indicating a broken IPv6 path), the problem persists even when IPv6 is completely disabled at the kernel level within the container (net.ipv6.conf.all.disable_ipv6 = 1). This was confirmed to be active via cat /proc/sys/net/ipv6/conf/all/disable_ipv6 returning 1. -
NODE_OPTIONS is Ineffective:
Setting export NODE_OPTIONS="--dns-result-order=ipv4first" in the remote user's profile (~/.profile or ~/.bash_profile) is correctly picked up by the extensionHost process (verified via ps aux), but it has no effect on the outcome. -
strace Reveals the Core Problem:
A trace of the extensionHost process (PID [PID]) shows the definitive cause of the failure:The extensionHost process correctly resolves the IPv4 address for api.github.com (e.g., 140.82.121.6).
It initiates a non-blocking socket connection with the connect() syscall. The kernel returns immediately, as expected:
[pid [PID]] connect(33, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("140.82.121.6")}, 16) = -1 EINPROGRESS (Operation now in progress)
Crucially, the strace log shows that the process never follows up on this connection. There are no subsequent poll(2) or select(2) calls on this socket descriptor (fd 33) to wait for the connection to be established. The process simply abandons the connection attempt.After the 10-second timeout configured in the undici library, the fetch operation fails, leading to the ConnectTimeoutError in the application log.
Hypothesis
The Node.js event loop within the VSCode Server's extensionHost process is malfunctioning in this specific environment. It successfully initiates a non-blocking connect operation but then fails to poll for or handle the socket's writability status. This causes the connection to never be established from the application's perspective, making all outgoing network requests from extensions impossible. This appears to be a runtime-level bug, as all user-level configurations (DNS, networking flags, system settings) are correct and have been proven ineffective.
Expected Behavior
The extensionHost process should correctly handle the non-blocking socket lifecycle, wait for the connection to be established using poll/select, and successfully communicate with external APIs, allowing extensions like GitHub Copilot to function.
Actual Behavior
The extensionHost process initiates but never completes TCP connections to external services, causing all network-dependent extension features to fail with timeouts, despite the underlying container having a perfectly functional network stack.