Fixing Empty Copilot Model List in VS Code Remote SSH (macOS Host)
Table of Contents
- 1. Environment and Problem Description
- 1.1 Basic Setup
- 1.2 The Problem
- 2. Troubleshooting: From DNS to SSL
- 2.1 Step 1: Check the Diagnostic Logs
- 2.2 Step 2: Dealing with DNS Blocking (AdGuard)
- 2.3 Step 3: Trying to Fix It via VS Code Settings (Failed)
- 3. The Final Solution: Modify the Remote Shell Configuration Directly
- 3.1 Modify the Remote Host’s Shell Config
- 3.2 Force Copilot to Use Node.js Fetcher
- 3.3 Completely Restart the Remote Server (Critical Step)
- 4. Common Pitfalls and Troubleshooting Tips
- 4.1 Only Modified settings.json, Didn’t Touch Shell Config
- 4.2 Only Reloaded the Window, Didn’t Kill VS Code Server
- 4.3 Confused DNS Blocking with SSL Issues
- 5. Summary: Environment Variable Propagation is Key
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.jsonsimply 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:
- Open the Command Palette (
Cmd+Shift+P/Ctrl+Shift+P) - Run the command: Remote-SSH: Kill VS Code Server on Host…
- Select the remote host’s IP/hostname
- 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_UNAUTHORIZEDinsettings.json, but the problem persists
Cause:
- In Remote SSH scenarios, environment variable propagation is complex, and
settings.jsonsettings 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 Hostto completely kill the remote process, then reconnect
4.3 Confused DNS Blocking with SSL Issues
Symptom:
- Saw
ECONNREFUSEDerrors 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: Diagnosticsto see the full logs first - Distinguish between
ECONNREFUSED(DNS/network issue) andunable 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:
-
Diagnostics first When you hit an issue, use
GitHub Copilot Chat: Diagnosticsto check logs instead of guessing -
settings.jsonisn’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 -
Restart thoroughly After changing low-level environment variables, use
Remote-SSH: Kill VS Code Server on Hostto completely restart, not just reload the window -
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.