Skip to content
This repository was archived by the owner on May 20, 2026. It is now read-only.
This repository was archived by the owner on May 20, 2026. It is now read-only.

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

@zahalzel

Description

@zahalzel

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:

$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:

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:

$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:

($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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions