Windows Copilot CLI shim crashes when Get-Command copilot returns null

Author: zahalzelCreated May 10, 2026Updated May 20, 2026

Bug

The Windows Copilot CLI shim can crash in Find-RealCopilot when Get-Command copilot returns no command.

Source file:

src/extension/chatSessions/vscode-node/copilotCLIShim.ps1

Current code:

powershell
$CopilotPath = (Get-Command copilot -ErrorAction SilentlyContinue).Source

# ...later:
if ($CurrentScript -eq $CopilotPath -or (Split-Path $CurrentScript -Parent) -eq (Split-Path $CopilotPath -Parent) -or ($CurrentScriptResolved -and $CopilotPathResolved -and $CurrentScriptResolved -eq $CopilotPathResolved)) {

When Get-Command copilot -ErrorAction SilentlyContinue finds nothing, $CopilotPath is $null. The second -or clause still evaluates when the first clause is false, so PowerShell runs:

powershell
Split-Path $CopilotPath -Parent

That throws because Split-Path cannot bind a null/empty path.

Why this matters

This is the exact case the shim appears intended to handle: bootstrap or install when no real copilot command is available, while avoiding recursion if the shim shadows the real binary. Instead, the lookup path can fail before the install/update prompt path runs cleanly.

I reproduced this from the generated shim written by VS Code Insiders Copilot Chat:

%APPDATA%\Code - Insiders\User\globalStorage\github.copilot-chat\copilotCli\copilot.ps1

Installed extension metadata on the affected machine:

name: copilot-chat
displayName: GitHub Copilot Chat
version: 0.48.2026050805
build: 1

The bundled source in the installed VS Code Insiders app contains the same unguarded Split-Path $CopilotPath -Parent expression.

Expected behavior

If Get-Command copilot finds no real CLI, the shim should not crash. It should continue to the existing missing/install flow or return $null from Find-RealCopilot.

Suggested fix

Guard the directory comparison before calling Split-Path on $CopilotPath, for example:

powershell
$CurrentScriptDir = if ($CurrentScript) { Split-Path $CurrentScript -Parent } else { $null }
$CopilotPathDir = if ($CopilotPath) { Split-Path $CopilotPath -Parent } else { $null }

if (-not $CopilotPath -or $CurrentScript -eq $CopilotPath -or ($CurrentScriptDir -and $CopilotPathDir -and $CurrentScriptDir -eq $CopilotPathDir) -or ($CurrentScriptResolved -and $CopilotPathResolved -and $CurrentScriptResolved -eq $CopilotPathResolved)) {

A smaller guard around only the existing second clause would also work:

powershell
($CopilotPath -and (Split-Path $CurrentScript -Parent) -eq (Split-Path $CopilotPath -Parent))

Notes

This does not appear to be a user-authored script. The generated file is under globalStorage\github.copilot-chat\copilotCli, and the same shim text is embedded in the shipped Copilot Chat extension bundle.

Source: microsoft/vscode-copilot-chat