Skip to content

fix: guard null diagnostic code in copilotcli diagnostics push (fixes #333772) - #333781

Merged
Don Jayamanne (DonJayamanne) merged 3 commits into
microsoft:mainfrom
vscodebot-pr:fix/copilotcli-diagnostics-null-code-aw-33521605933
Sep 2, 2026
Merged

fix: guard null diagnostic code in copilotcli diagnostics push (fixes #333772)#333781
Don Jayamanne (DonJayamanne) merged 3 commits into
microsoft:mainfrom
vscodebot-pr:fix/copilotcli-diagnostics-null-code-aw-33521605933

Conversation

@vscodebot-pr

Copy link
Copy Markdown
Contributor

Summary

A TypeError: Cannot read properties of null (reading 'value') fires in the Copilot CLI diagnostics-push notification path (diagnosticsChanged.ts). When VS Code reports a diagnostic whose code is null, the serialization code does typeof d.code === 'object' ? d.code.value : d.code. Because typeof null === 'object', the ternary takes the object branch and dereferences null.value, throwing. The throw escapes through Array.map and the Delayer task, surfacing as an unhandled error for ~136 users on 0.63.0.

Fixes #333772
Recommended reviewer: @DonJayamanne

Culprit Commit

Field Value
Commit ab48d553b30
Author @alexweininger
PR #3529
Message Migrate Copilot CLI integration (#3529)
Why This commit introduced diagnosticsChanged.ts with the line code: typeof d.code === 'object' ? d.code.value : d.code. The typeof ... === 'object' test is true for null, so a null diagnostic code takes the object branch and dereferences null.value. It is an ancestor of the shipped commit 08d4889.

The bucket first appears in 0.63.0 (baseline 0.62.0 clean). The reading 'start' sibling variant (422ad33e) also maps to this same EVo map site — a null d.range would fail the same way one line up — but the representative bucket is the null code dereference.

Code Flow

sequenceDiagram
    participant VSCode as vscode.languages
    participant Handler as onDidChangeDiagnostics
    participant Producer as getDiagnosticsForUri
    participant CrashSite as diagnostics.map(d => ...)

    VSCode->>Handler: DiagnosticChangeEvent (diagnostic.code === null)
    Handler->>Producer: event.uris.map(getDiagnosticsForUri)
    Note over Producer: Root cause: typeof null === 'object' is true
    Producer->>CrashSite: diagnostics.map(d => code from d.code.value)
    Note over CrashSite: TypeError: Cannot read properties of null (reading 'value')
Loading

Affected Files

File Role Evidence
extensions/copilot/src/extension/chatSessions/copilotcli/vscode-node/tools/push/diagnosticsChanged.ts crash site + root cause L52: code: typeof d.code === 'object' ? d.code.value : d.codetypeof null === 'object' reaches null.value

Repro Steps

  1. Open a Copilot CLI chat session with the diagnostics-push MCP notification active.
  2. Trigger a language diagnostic whose code is null (many linters/language servers emit a diagnostic with no code, surfaced as null rather than undefined).
  3. The onDidChangeDiagnostics handler runs getDiagnosticsForUri, maps the diagnostic, and evaluates typeof d.code === 'object' ? d.code.value : d.code.
  4. Since typeof null === 'object', the code dereferences null.value and throws the unhandled TypeError.

How the Fix Works

Chosen approachdiagnosticsChanged.ts L52: add an explicit && d.code !== null to the object-branch guard so a null code falls through to the else branch and is emitted as-is:

code: typeof d.code === 'object' && d.code !== null ? d.code.value : d.code,

This fixes the bug at the data producer (the serialization of the diagnostic), which is exactly where the invalid dereference occurs — not at a crash site further down or via a try/catch that would swallow the error and break telemetry. The VS Code Diagnostic.code type is string | number | { value; target }, but the runtime value can legitimately be null; the pre-existing typeof ... === 'object' check simply forgot the classic typeof null footgun. The null code now serializes to null, matching the intent for a diagnostic with no structured code.

Alternatives considered:

  • Wrapping the .map() in try/catch — rejected because it hides the error from the telemetry pipeline instead of fixing the data producer, and would silently drop every diagnostic in a batch once one is malformed.
  • Using d.code?.value optional chaining — rejected because it still takes the object branch for null and would emit undefined rather than the intended null, and does not express the actual invariant (null is not a structured code object).

Recommended Owner

@DonJayamanne — the dominant and currently-active contributor to the Copilot CLI (copilotcli) integration area in microsoft/vscode. The culprit author (@alexweininger) has no commits to the repo in the last 90 days, so ownership falls to the active area maintainer.

Generated by errors-fix · opus48 · 379.2 AIC · ⌖ 17.9 AIC · ⊞ 18.6K ·

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prevents Copilot CLI diagnostic push notifications from crashing when a diagnostic code is null.

Changes:

  • Adds a null guard before reading a structured diagnostic code’s value.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vs-code-engineering

Copy link
Copy Markdown
Contributor
Driver cycle recordederrors-fix-driver:cycle head:886cfb6d7f3b6dd7784a1b659b3d9869f39c5a4a

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Move the null diagnostic code regression coverage into the existing
diagnosticsChanged.spec.ts suite so the Copilot vitest config
(**/*.spec.ts) actually runs it, and drop the uncollected
tools/push/test/diagnosticsChanged.test.ts. Revert the serializeDiagnostic
export extraction that was only needed by the removed test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vs-code-engineering

Copy link
Copy Markdown
Contributor
Driver cycle recordederrors-fix-driver:cycle head:bd41a6fc10f9e02acdb94ba649693217482b865a

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Note

This error may be related to your runner configuration. You can now configure runners for Copilot code review separately from Copilot cloud agent by creating a copilot-code-review.yml file with your setup steps. Read the docs for details.

@vs-code-engineering

Copy link
Copy Markdown
Contributor

The failing Electron-Unit checks (Linux/Windows/macOS) exercise core src/ unit tests and are unaffected by this Copilot-only diff, so they look unrelated/flaky and need a maintainer rerun (the driver lacks actions: write). The PR is already approved and both review threads are resolved.

@DonJayamanne
Don Jayamanne (DonJayamanne) merged commit 1f625ad into microsoft:main Sep 2, 2026
27 of 30 checks passed
@vs-code-engineering vs-code-engineering Bot added this to the 1.137.0 milestone Sep 2, 2026
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] [GitHub.copilot-chat] unhandlederror-Cannot read properties of null (reading 'value')

5 participants