Skip to content

fix: skip NES streamed edits for unknown target documents (fixes #326359)#326360

Open
vs-code-engineering[bot] wants to merge 1 commit into
mainfrom
fix/nes-unknown-target-doc-326359-f6e1c527f4db86df
Open

fix: skip NES streamed edits for unknown target documents (fixes #326359)#326360
vs-code-engineering[bot] wants to merge 1 commit into
mainfrom
fix/nes-unknown-target-doc-326359-f6e1c527f4db86df

Conversation

@vs-code-engineering

Copy link
Copy Markdown
Contributor

Summary

The Next Edit Suggestion (NES) path throws BugIndicatingError ("An unexpected bug occurred.") with high frequency — 468 users / 3,245 hits on GitHub.copilot-chat 0.57.0 (win32), plus ~920 more users across drifted sibling buckets (d5ee2c95, a0c33451, 0be6ac5b, f5de1e2e).

The crash originates in createDocStateLookupMap (extensions/copilot/src/extension/inlineEdits/node/nextEditProvider.ts:148): when a streamed edit produced by the model targets a document that is neither one of the request's projected documents nor an edit-history entry, the CachedFunction lookup falls through to throw new BugIndicatingError(). The streamed edit's targetDocument is model output — an untrusted boundary — so an unrecognised document id is a normal runtime possibility, not a programming invariant violation, and must not be reported as an unexpected bug.

The fix validates the model-produced targetDocument at the boundary (_rebaseAndCacheStreamedEdit) and skips unknown-document edits, returning undefined — a result both callers already handle gracefully as "edit could not be rebased".

Fixes #326359
Recommended reviewer: @alexr00

Culprit Commit

The error is a genuinely new signature between copilot-chat 0.51.0 (baseline, absent) and 0.57.0 (VS Code 1.129.0), per the errors-regression-scan comment. The local checkout is a shallow (depth-1) clone, so per-line history before the checkout commit is not retrievable and an exact culprit SHA could not be confirmed offline. git blame attributes the current createDocStateLookupMap / _rebaseAndCacheStreamedEdit code (including the throw new BugIndicatingError() fall-through and the xtabEditHistory fallback loop) to recent work by Alex Ross (@alexr00). The regression coincides with the cross-file / streamed-edit rebase refactor that introduced the statePerDoc lookup map keyed by model-supplied targetDocument ids.

Code Flow

flowchart TD
    A["getNextEdit"] --> B["_getNextEditCanThrow"]
    B --> C["fetchNextEdit"]
    C --> D["_executeNewNextEditRequest"]
    D --> E["editStream: model streams StreamedEdit (targetDocument is model-produced)"]
    E --> F["processEdit(streamedEdit)"]
    F --> G["_rebaseAndCacheStreamedEdit"]
    G --> H["statePerDoc.get(streamedEdit.targetDocument) cache.ts:117"]
    H --> I{"doc in projectedDocuments or xtabEditHistory?"}
    I -->|yes| J["return DocState"]
    I -->|no| K["throw new BugIndicatingError() nextEditProvider.ts:148"]
    K --> L["unhandled: 'An unexpected bug occurred.' -> error telemetry"]
Loading

Affected Files

File Role Change
extensions/copilot/src/extension/inlineEdits/node/nextEditProvider.ts Producer boundary + crash site Validate model-produced targetDocument before the statePerDoc lookup; skip unknown-document streamed edits instead of throwing.

Repro Steps

  1. Trigger a Next Edit Suggestion in a file (inline edits / NES enabled).
  2. Have the model stream a StreamedEdit whose targetDocument is not among the request's projected documents and not present as an 'edit' entry in xtabEditHistory (e.g. a cross-file suggestion referencing a document that was not included in the request context).
  3. _rebaseAndCacheStreamedEdit calls statePerDoc.get(streamedEdit.targetDocument), the CachedFunction body falls through both lookups and throws BugIndicatingError, surfacing as the unhandled "An unexpected bug occurred." error.

How the Fix Works

Chosen approach (extensions/copilot/src/extension/inlineEdits/node/nextEditProvider.ts):

  • createDocStateLookupMap now returns { statePerDoc, isKnownDocument }, where isKnownDocument(id) reports — without throwing — whether statePerDoc.get(id) can resolve a document (present in projectedDocuments, or an 'edit' entry in xtabEditHistory). This reuses exactly the same membership logic the lookup body uses.
  • _rebaseAndCacheStreamedEdit guards the model-produced streamedEdit.targetDocument with isKnownDocument(...) before calling statePerDoc.get(...). When the target is unknown it logs a trace and returns undefined.
  • Both call sites (_executeNewNextEditRequest and _runSpeculativeProviderCall) already treat an undefined result as "edit could not be rebased" and skip it, so the streamed edit is dropped cleanly rather than crashing the stream.

This is a guard clause placed at the model-output boundary — the point where untrusted data first enters the typed DocumentId -> DocState lookup — rather than at the crash site inside the cached function (fix at the data producer, not the crash site). The bypass site is nextEditProvider.ts:148, reached only via the model-supplied targetDocument; the guard sits at the sole producer path that can feed it an unvalidated id. The throw new BugIndicatingError() is deliberately left in place: it still correctly guards the internal invariant that curDocId (the active document, always a projected document) is resolvable, so a genuine internal misuse would still be reported. After this change, nextEditProvider.ts:776 cannot forward an unknown model-produced targetDocument into statePerDoc.get, because the isKnownDocument guard returns early for exactly the ids that would otherwise reach the throw.

Alternatives considered:

  • Wrapping the statePerDoc.get(...) call in try/catch — rejected because it hides the model-boundary condition behind exception handling and would also swallow genuine internal invariant violations, degrading telemetry instead of fixing the data path.
  • Making the CachedFunction body return undefined for unknown ids — rejected because DocState is consumed as non-nullable at several sites (e.g. statePerDoc.get(curDocId)), so weakening the map's contract would ripple null-checks across unrelated, always-valid call sites.

Recommended Owner

@alexr00 — Alex Ross authored the current createDocStateLookupMap / _rebaseAndCacheStreamedEdit streamed-edit rebase code containing the crash site, and the regression tracks the cross-file streamed-edit refactor introduced between 0.51.0 and 0.57.0.

Generated by errors-fix · 2.9K AIC · ⌖ 35.2 AIC · ⊞ 71K ·

)

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

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 can't review bot-authored pull requests automatically. A user with Copilot access can request a review manually.

@vs-code-engineering
vs-code-engineering Bot requested review from alexr00 and Copilot July 17, 2026 15:18

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 can't review bot-authored pull requests automatically. A user with Copilot access can request a review manually.

@vs-code-engineering
vs-code-engineering Bot marked this pull request as ready for review July 17, 2026 15:19
@vs-code-engineering
vs-code-engineering Bot enabled auto-merge (squash) July 17, 2026 15:19
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-An unexpected bug occurred.

2 participants