Skip to content

fix: guard against null rightUri in SCM resolveChangeCommand (fixes #315292)#315341

Open
vs-code-engineering[bot] wants to merge 1 commit intomainfrom
fix/scm-null-uri-315292-c6dcc1e9d7ba1881
Open

fix: guard against null rightUri in SCM resolveChangeCommand (fixes #315292)#315341
vs-code-engineering[bot] wants to merge 1 commit intomainfrom
fix/scm-null-uri-315292-c6dcc1e9d7ba1881

Conversation

@vs-code-engineering
Copy link
Copy Markdown
Contributor

🔧 Error Fix

Summary

Error: Cannot read properties of null (reading 'scheme') — a TypeError thrown when opening an SCM resource in the editor via URI.from() with a null argument.

Root cause: In the git extension's ResourceCommandResolver.resolveChangeCommand(), when leftUri is falsy and the merge-editor branch is not taken, resource.rightUri is passed directly as the first argument to the vscode.open command. For certain git status types (BOTH_DELETED, ADDED_BY_US, ADDED_BY_THEM, etc.), getRightResource() returns {}, making rightUri undefined. After serialization through the extension host protocol boundary, undefined becomes null in JSON, so the _workbench.open command handler receives null as resourceArg and calls URI.from(null), which crashes reading null.scheme.

Impact: 875 users affected on stable 1.119.0 across Windows, Mac, and Linux.

Fixes #315292
Recommended reviewer: @lszomoru

Culprit Commit

This is a latent bug — the code path has existed for a long time. No single culprit commit introduced it. The regression in 1.119.0 is likely due to a change in user behavior or new SCM status types triggering the unguarded path. Prior occurrences: #244373, #230645.

Code Flow

sequenceDiagram
    participant User
    participant SCMViewPane as scmViewPane.ts
    participant CommandService as commandService.ts
    participant EditorCommands as editorCommands.ts
    participant URI as uri.ts
    participant GitExt as git/repository.ts

    User->>SCMViewPane: Click SCM resource
    SCMViewPane->>SCMViewPane: open() at line 1726
    Note over SCMViewPane: e.element.command.arguments[0] is null
    SCMViewPane->>CommandService: executeCommand('_workbench.open', null, ...)
    CommandService->>EditorCommands: handler(resourceArg=null)
    EditorCommands->>URI: URI.from(null, true)
    URI-->>URI: 💥 null.scheme → TypeError
    Note over GitExt: Producer: resolveChangeCommand()<br/>passes rightUri (undefined) as arg[0]<br/>serialized to null across ext host boundary
Loading

Affected Files

File Role
extensions/git/src/repository.ts ProducerresolveChangeCommand() passes potentially-undefined rightUri as command argument
src/vs/workbench/browser/parts/editor/editorCommands.ts:463 Crash site — URI.from(resourceArg) where resourceArg is null
src/vs/base/common/uri.ts:343 Terminal crash — reads components.scheme on null
src/vs/workbench/contrib/scm/browser/scmViewPane.ts:1726 Dispatcher — spreads command arguments into executeCommand

Repro Steps

  1. Have a git repository with a file in a conflict state that produces a status like BOTH_DELETED or ADDED_BY_US
  2. With git.openDiffOnClick enabled (default), click on the resource in the SCM view
  3. The resolveChangeCommand produces a command with rightUri = undefined
  4. After ext host serialization, the _workbench.open handler receives null → crash

How the Fix Works

Chosen approach (extensions/git/src/repository.ts): Changed line 543 from resource.rightUri to resource.rightUri ?? resource.resourceUri. This fixes the problem at the data producer — resolveChangeCommand() is where the invalid (undefined) value enters the command arguments array. The resourceUri getter always returns a valid Uri (it is typed as non-nullable), so it is a safe fallback. This follows the principle of fixing at the data producer rather than guarding at the crash site.

Alternatives considered: Adding a null guard in editorCommands.ts before URI.from() — rejected because that would be a crash-site guard that silences the error without fixing the producer, and would mask any future callers passing invalid data through the command bus.

Recommended Owner

@lszomoru — primary maintainer of the git extension (extensions/git/) and author of most recent changes to repository.ts.

Generated by errors-fix · ● 6M ·

…315292)

When rightUri is undefined for certain git status types (e.g. BOTH_DELETED,
ADDED_BY_US), resolveChangeCommand passes undefined to the vscode.open
command. After serialization through the extension host boundary, undefined
becomes null, causing URI.from(null) to throw 'Cannot read properties of
null (reading scheme)'.

Fall back to resource.resourceUri (always defined) when rightUri is
undefined.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Error] unhandlederror-Cannot read properties of null (reading 'scheme')

1 participant