Fixing Empty Copilot Model List in VS Code Remote SSH (macOS Host)

2025年12月31日 | Ruichen Zhou
VS CodeGitHub CopilotSSHmacOSRemote Development

Fixing Empty Copilot Model List in VS Code Remote SSH (macOS Host)

This post documents a pretty specific issue I ran into: when using VS Code Remote SSH to connect to a remote Mac, the GitHub Copilot model selection dropdown was completely empty. I couldn’t switch between GPT-4o, Claude 3.5 Sonnet, or any other models—the dropdown just showed nothing.

At first, I thought it was a proxy configuration issue and spent a while tweaking settings.json in VS Code. That didn’t work at all. The final solution turned out to be more “brute force”: directly disabling Node.js SSL verification in the remote Mac’s shell configuration.

Below is the complete troubleshooting process and the final solution, documented for future reference.


1. Environment and Problem Description

1.1 Basic Setup

  • Client: Windows 11, VS Code Insiders
  • Remote Host: macOS (Apple Silicon), accessed via SSH
  • Network: Local network with AdGuard Home for DNS filtering
  • Extension: GitHub Copilot Chat (Pre-release version)

1.2 The Problem

When I opened Copilot Chat and clicked the model selection dropdown, it was completely empty—no options at all.

Normally, you’d see:

  • GPT-4o
  • Claude 3.5 Sonnet
  • o1-preview
  • etc.

But in my case, it was just a blank dropdown.


2. Troubleshooting: From DNS to SSL

2.1 Step 1: Check the Diagnostic Logs

Instead of guessing, I went straight to VS Code’s built-in diagnostic tool.

In the Command Palette (Cmd+Shift+P / Ctrl+Shift+P), I ran:

GitHub Copilot Chat: Diagnostics

The output logs showed two types of errors:

Error 1: SSL/TLS Certificate Issue

Error: unable to get issuer certificate

This meant the Node.js process running Copilot on the remote Mac didn’t trust the SSL certificate chain.

This is pretty common in corporate networks or when you have local network tools (like transparent proxies) interfering with HTTPS traffic. In my case, I had AdGuard Home running on my router, which might have been messing with things.

Error 2: Connection Refused

Error: connect ECONNREFUSED 0.0.0.0:443

This error was specific to Microsoft telemetry domains like mobile.events.data.microsoft.com.

2.2 Step 2: Dealing with DNS Blocking (AdGuard)

The ECONNREFUSED 0.0.0.0 error was clearly caused by AdGuard Home blocking Microsoft’s telemetry domains.

I initially thought this was the main issue, so I added these domains to AdGuard’s allowlist:

@@||github.com^
@@||api.github.com^
@@||githubcopilot.com^

After that, the ECONNREFUSED errors disappeared.

But the model list was still empty.

This proved that DNS blocking was only a secondary issue. The real problem was still that SSL certificate error.

2.3 Step 3: Trying to Fix It via VS Code Settings (Failed)

Since it was an SSL certificate issue, my first instinct was to disable SSL verification in settings.json:

"http.proxyStrictSSL": false,
"remote.SSH.serverEnv": {
    "NODE_TLS_REJECT_UNAUTHORIZED": "0"
}

I saved the file and reconnected to the remote host.

Result: Didn’t work at all.

Why it failed:

In Remote SSH scenarios (especially when connecting to macOS), environment variables set in VS Code’s settings.json often fail to propagate correctly to the extension host process.

This is due to shell loading order issues:

  • Interactive shells read .zshrc / .bashrc
  • Login shells read .zprofile / .bash_profile
  • When VS Code Server starts extensions, it might use one of these paths, and the environment variables from settings.json simply don’t make it through

3. The Final Solution: Modify the Remote Shell Configuration Directly

Since settings.json didn’t work, I decided to write the environment variable directly into the remote Mac’s shell configuration files.

3.1 Modify the Remote Host’s Shell Config

On the remote macOS machine, I added the environment variable to both .zshrc and .zprofile to ensure it would work regardless of which shell startup method was used.

In the remote terminal, I ran:

echo 'export NODE_TLS_REJECT_UNAUTHORIZED=0' >> ~/.zshrc
echo 'export NODE_TLS_REJECT_UNAUTHORIZED=0' >> ~/.zprofile
source ~/.zshrc

Verify it worked:

echo $NODE_TLS_REJECT_UNAUTHORIZED

This should output 0.

3.2 Force Copilot to Use Node.js Fetcher

In the local VS Code settings.json, I also added these two lines to force Copilot to use the Node.js fetch implementation (instead of Electron’s), since the Node.js fetcher responds more reliably to environment variables:

"github.copilot.advanced.debug.useNodeFetcher": true,
"github.copilot.advanced.debug.useElectronFetcher": false

3.3 Completely Restart the Remote Server (Critical Step)

This step is absolutely critical and easy to overlook.

Don’t just do Developer: Reload Window, because the VS Code Server process might still be running in the background with the old environment variables.

The correct approach:

  1. Open the Command Palette (Cmd+Shift+P / Ctrl+Shift+P)
  2. Run the command: Remote-SSH: Kill VS Code Server on Host…
  3. Select the remote host’s IP/hostname
  4. Reconnect to the remote host

After doing this, the Copilot model list immediately appeared, all models were selectable, and Chat functionality was restored.


4. Common Pitfalls and Troubleshooting Tips

Based on this experience, here are a few common mistakes to avoid.

4.1 Only Modified settings.json, Didn’t Touch Shell Config

Symptom:

  • Set NODE_TLS_REJECT_UNAUTHORIZED in settings.json, but the problem persists

Cause:

  • In Remote SSH scenarios, environment variable propagation is complex, and settings.json settings might not reach the extension process

Solution:

  • Write the environment variable directly into the remote host’s .zshrc / .zprofile

4.2 Only Reloaded the Window, Didn’t Kill VS Code Server

Symptom:

  • After changing the config, ran Developer: Reload Window, but the problem remains

Cause:

  • The VS Code Server process might still be running in the background with old environment variables

Solution:

  • Use Remote-SSH: Kill VS Code Server on Host to completely kill the remote process, then reconnect

4.3 Confused DNS Blocking with SSL Issues

Symptom:

  • Saw ECONNREFUSED errors and thought fixing DNS blocking would solve everything

Reality:

  • DNS blocking and SSL certificates are two separate issues
  • Need to handle them separately: DNS blocking → allowlist; SSL issue → environment variable

Troubleshooting tip:

  • Use GitHub Copilot Chat: Diagnostics to see the full logs first
  • Distinguish between ECONNREFUSED (DNS/network issue) and unable to get issuer certificate (SSL issue)

5. Summary: Environment Variable Propagation is Key

The core of this problem wasn’t actually Copilot itself, but rather how VS Code Remote SSH handles environment variable propagation.

Key takeaways:

  1. Diagnostics first When you hit an issue, use GitHub Copilot Chat: Diagnostics to check logs instead of guessing

  2. settings.json isn’t a silver bullet In Remote SSH scenarios, the most reliable way to set environment variables is to write them directly into the remote host’s shell config files

  3. Restart thoroughly After changing low-level environment variables, use Remote-SSH: Kill VS Code Server on Host to completely restart, not just reload the window

  4. Distinguish between different error types DNS blocking (ECONNREFUSED) and SSL certificates (unable to get issuer certificate) are different issues that need separate solutions

This solution is a bit “brute force” (directly disabling SSL verification), but it’s acceptable in a local development environment. For production or security-sensitive scenarios, the better approach would be to configure the correct certificate chain instead of disabling verification.


If you run into similar extension behavior issues with Remote SSH in the future, the first question to ask is: Did the environment variable actually make it through? This approach applies to many scenarios beyond just this one.