Skip to content

fix: guard against undefined gitRepository in _resolveGitState (fixes #316628)#316629

Open
vs-code-engineering[bot] wants to merge 1 commit into
mainfrom
fix/github-contribution-gitHubInfo-undefined-316628-0bdfd148f5b5c6e5
Open

fix: guard against undefined gitRepository in _resolveGitState (fixes #316628)#316629
vs-code-engineering[bot] wants to merge 1 commit into
mainfrom
fix/github-contribution-gitHubInfo-undefined-316628-0bdfd148f5b5c6e5

Conversation

@vs-code-engineering

@vs-code-engineering vs-code-engineering Bot commented May 15, 2026

Copy link
Copy Markdown
Contributor

🔧 Error Fix

Summary

Error: TypeError: Cannot read properties of undefined (reading 'get')
Location: src/vs/sessions/contrib/github/browser/github.contribution.ts:114 (_startPolling)
Impact: 43 affected users on 1.121.0-insider across Mac, Windows, Linux

The LocalNewSession._resolveGitState() method spreads this.sessionWorkspace.folders[0].gitRepository! with a non-null assertion. When the initial workspace folder has no gitRepository (it is optional on ISessionFolder since the refactor in 1e8d5ef), the spread of undefined produces an object without gitHubInfo, violating the ISessionGitRepository type contract. Downstream, _startPolling in github.contribution.ts accesses .gitHubInfo.get() on this malformed object, triggering the TypeError.

Fixes #316628
Recommended reviewer: @sandy081

Culprit Commit

1e8d5efd by @sandy081 — "sessions: refactor ISession workspace model — ISessionFolder, ISessionGitRepository"

This refactoring made gitRepository optional on ISessionFolder but did not update the non-null assertion in LocalNewSession._resolveGitState(), leaving a path where undefined is spread into a partial ISessionGitRepository object.

Code Flow

flowchart TD
    A["copilotChatSessionsProvider: _refreshSessionCacheMultiChat"] -->|fires onDidChangeSessions| B["sessionsManagementService: onDidChangeSessionsFromSessionsProviders"]
    B -->|fires event| C["github.contribution: _onDidChangeSessions"]
    C -->|iterates added sessions| D["github.contribution: _startPolling"]
    D -->|accesses session.workspace.get?.folders gitRepository?.gitHubInfo.get| E["CRASH: gitHubInfo is undefined"]
    F["LocalNewSession._resolveGitState"] -->|spreads undefined gitRepository!| G["Produces malformed ISessionGitRepository without gitHubInfo"]
    G -->|stored in _workspaceData observable| D
Loading

Affected Files

File Role
src/vs/sessions/contrib/providers/copilotChatSessions/browser/copilotChatSessionsProvider.ts ProducerLocalNewSession._resolveGitState() spreads undefined gitRepository
src/vs/sessions/contrib/github/browser/github.contribution.ts Crash site_startPolling accesses .gitHubInfo.get()
src/vs/sessions/services/sessions/common/session.ts Type definitionISessionGitRepository.gitHubInfo is non-optional

Repro Steps

  1. Create a LocalNewSession with a workspace whose folders[0].gitRepository is undefined
  2. _resolveGitState successfully opens a git repository and the autorun fires
  3. The spread ...this.sessionWorkspace.folders[0].gitRepository! produces {branchName, upstreamBranchName, uncommittedChanges} (missing gitHubInfo, uri, etc.)
  4. _refreshSessionCacheMultiChat fires onDidChangeSessions with this session
  5. _startPolling accesses .gitRepository?.gitHubInfo.get()gitRepository is truthy (non-empty object) so optional chain doesn't short-circuit, but gitHubInfo is undefined → crash

How the Fix Works

Chosen approach (copilotChatSessionsProvider.ts:858): Replace the non-null assertion spread with a conditional — only create the updated gitRepository when the original exists, preserving undefined otherwise. This fixes at the data producer (where the malformed object is created), not the crash site. After this change, line 858 cannot produce an ISessionGitRepository without gitHubInfo because when this.sessionWorkspace.folders[0].gitRepository is undefined, gitRepository is set to undefined (not a partial object), and consumers correctly short-circuit via ?.gitRepository?..

Recommended Owner

@sandy081 — authored the culprit refactoring commit that made gitRepository optional without updating the spread site.

errors-fix-driver — cycle 4

Trigger: cron_merge_conflict · Head (pre-push): b865d521ffe189d734be0f09577ee81afed2ce7c (b865d52)

Item Action
Merge conflict in copilotChatSessionsProvider.ts (state dirty) Resolved by taking main's version. The LocalNewSession class this PR patches was refactored out of copilotChatSessionsProvider.ts into localChatSessionsProvider.ts, so main no longer carries the conflicting code. Resolved tree is byte-identical to main — verified locally with an empty git diff origin/main HEAD.
Underlying bug #316628 Already fixed on main. The relocated _resolveGitState in localChatSessionsProvider.ts falls back to { ..., gitHubInfo: constObservable(undefined) } when a folder has no gitRepository, so no code path can emit an ISessionGitRepository without gitHubInfo; the crash site in github.contribution.ts is unreachable with a malformed object.
CI All required checks green; only Community PR Approvals is in_progress (a gating check, not a failure). No real or transient failures.
Reviews No unresolved review threads. Two Copilot reviews errored ("unable to review"); no human change requests.

Push: declared this cycle — a merge-resolution commit bringing the branch tree in line with main (3106-file catch-up + conflict resolution) to clear the persistent dirty state. The push handler bundled the change and returned success but no SHA to cite; confirm on the branch. Copilot rerequested: n/a — zero net diff vs main, nothing new to review.

Ready gate: not ready — superseded. #316628 is already fixed on main and the patched LocalNewSession class was refactored away, so this PR contributes no net change (empty diff vs main). The driver cannot close PRs and will not mark a zero-value PR ready. Recommend @sandy081 close this PR as superseded / obsolete.

Generated by errors-fix · ● 73.2M ·

Generated by errors-fix-driver · ● 22.5M ·

Generated by errors-fix-driver · 2.3K AIC · ⌖ 129.8 AIC · ⊞ 71.2K ·

Generated by errors-fix-driver · 1.8K AIC · ⌖ 209.3 AIC · ⊞ 71.2K ·

Generated by errors-fix-driver · 1.7K AIC · ⌖ 512.7 AIC · ⊞ 71.2K ·

…316628)

The _resolveGitState method in LocalNewSession spreads
this.sessionWorkspace.folders[0].gitRepository with a non-null assertion.
When the initial workspace folder has no gitRepository (it is optional on
ISessionFolder), the spread of undefined produces an object without
gitHubInfo, violating the ISessionGitRepository type contract. Downstream,
_startPolling in github.contribution.ts accesses .gitHubInfo.get() on this
malformed object, triggering the TypeError.

The fix conditionally creates the updated gitRepository only when the
original exists, preserving undefined otherwise so consumers correctly
short-circuit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 15, 2026 15:36

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.

@vs-code-engineering vs-code-engineering Bot requested review from Copilot and sandy081 May 15, 2026 15:40

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.

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 undefined (reading 'get')

2 participants