Skip to content

fix: don't report NES fetch failures as unexpected errors (fixes #325643)#325649

Open
vs-code-engineering[bot] wants to merge 1 commit into
mainfrom
fix/nes-network-error-telemetry-325643-a7f2465561928189
Open

fix: don't report NES fetch failures as unexpected errors (fixes #325643)#325649
vs-code-engineering[bot] wants to merge 1 commit into
mainfrom
fix/nes-network-error-telemetry-325643-a7f2465561928189

Conversation

@vs-code-engineering

Copy link
Copy Markdown
Contributor

Summary

Benign, transient network failures from the Copilot Next Edit Suggestions (NES / xtab) fetch are being reported to error telemetry as unexpected errors, generating noise like unhandlederror-An unexpected error occurred: {"type":"networkError","reason":"...net::ERR_NAME_NOT_RESOLVED."}.

When the NES request fails (here a DNS failure, net::ERR_NAME_NOT_RESOLVED), the fetch error is modeled as a NoNextEditReason.FetchFailure. _getNextEditCanThrow then re-throws that modeled reason as an exception. Because the getNextEdit() promise is one of the racers passed to raceAndAll(promises, onUnexpectedError) in inlineCompletionProvider.ts, raceAndAll forwards every racer rejection to its errorHandler — which is onUnexpectedError. So a benign connectivity failure ends up in the unexpected-error telemetry pipeline (surfacing via onUnexpectedError in src/vs/base/common/errors.ts, the deepest deminified frame).

FetchFailure is a first-class expected reason, not a programming error — a failed fetch simply means "no suggestion right now". Genuine internal errors are modeled separately as NoNextEditReason.Unexpected. The fix stops converting the expected FetchFailure reason into a thrown exception while keeping Unexpected throwing.

Fixes #325643
Recommended reviewer: @ulugbekna

Culprit Commit

Not pinpointed to a single commit within the time budget (shallow clone; no local git log). The relevant machinery is:

  • raceAndAll error handling — last touched by a28a677cfd6b7af2fa276d4fc662cff9be0c800f "Fix raceAndAll error handling (C# "Language mode" disappeared from the list #3996)" (@benibenj), which forwards all racer rejections to the supplied errorHandler.
  • The raceAndAll(..., onUnexpectedError) NES call site and the FetchFailure/Unexpected re-throw in nextEditProvider.ts predate that and belong to the NES/inline-edits feature area (@ulugbekna).

The bug is the interaction: an expected FetchFailure is thrown by the NES provider and then classified as unexpected by the race error handler.

Code Flow

flowchart TD
    A[xtab _performFetch: DNS failure net::ERR_NAME_NOT_RESOLVED] --> B[mapChatFetcherErrorToNoNextEditReason]
    B -->|NetworkError case| C[NoNextEditReason.FetchFailure ErrorUtils.fromUnknown]
    C --> D[_getNextEditCanThrow]
    D -->|OLD: throw error.error| E[getNextEdit rejects]
    E --> F["raceAndAll(promises, onUnexpectedError) racer rejects"]
    F -->|errorHandler(error)| G[onUnexpectedError]
    G --> H[error telemetry: 'An unexpected error occurred']
    D -->|NEW: FetchFailure handled, return empty result| I[No throw - no suggestion, telemetry status noEdit:fetchFailure]
Loading

Affected Files

File Role Change
extensions/copilot/src/extension/inlineEdits/node/nextEditProvider.ts NES provider — classifies the request outcome Only NoNextEditReason.Unexpected re-throws; NoNextEditReason.FetchFailure is now handled as an expected non-result (logged, telemetry status set) instead of thrown

Supporting (unchanged) context:

  • extensions/copilot/src/extension/xtab/node/xtabProvider.tsmapChatFetcherErrorToNoNextEditReason maps NetworkErrorFetchFailure.
  • extensions/copilot/src/extension/inlineEdits/vscode-node/inlineCompletionProvider.tsraceAndAll(..., onUnexpectedError) racer whose rejection was being reported.
  • extensions/copilot/src/extension/inlineEdits/vscode-node/raceAndAll.ts — forwards every racer rejection to errorHandler.

Repro Steps

  1. Enable Copilot NES (inline edits).
  2. Put the machine in a state where the model endpoint cannot be resolved (offline / DNS failure / firewall blocking name resolution).
  3. Type in a document to trigger an NES request.
  4. The xtab fetch fails with net::ERR_NAME_NOT_RESOLVED; before this change the resulting FetchFailure is thrown and reported via onUnexpectedError, producing the unhandlederror-An unexpected error occurred: {"type":"networkError",...} telemetry event. After this change the request resolves with no suggestion and no unexpected-error report.

How the Fix Works

Chosen approach — nextEditProvider.ts: Split the combined FetchFailure || Unexpected branch. NoNextEditReason.Unexpected continues to throw error.error (genuine programming errors stay observable). NoNextEditReason.FetchFailure is now handled inline as an expected outcome: it logs the failure (logger.trace, logContext.setError), records the diagnostic signal on telemetry (setNextEditProviderError, status noEdit:fetchFailure), and falls through to the existing empty-result return. This is the data-producer principle applied at the right layer — the NES provider is the producer of the rejected getNextEdit() promise, so preventing it from throwing an expected fetch failure stops the rejection at its source rather than filtering it downstream at the crash site (onUnexpectedError). No logService.error/telemetry call is removed and no try/catch is added; a modeled expected reason simply stops being re-thrown as an exception.

Alternatives considered:

  • Filter expected errors at the raceAndAll(..., onUnexpectedError) call site. Rejected: it fixes the reporting boundary (near the crash site) rather than the producer, and reliably detecting a network error there requires string-matching the flattened fromUnknown message (ErrorUtils.fromUnknown collapses the structured ChatFetchError into a generic Error), which is fragile.
  • Map NetworkError to GotCancelled / NoSuggestions in mapChatFetcherErrorToNoNextEditReason. Rejected: it mislabels a network failure as a cancellation or an empty-model-response, polluting those telemetry categories and hit-rate metrics.

Recommended Owner

@ulugbekna — active owner of the NES / inline-edits feature area (extensions/copilot/src/extension/inlineEdits/**, xtab/**) with recent commits to these exact files (e.g. 652b4aaa per-language NES gating, b5f83615 NES telemetry). Team member with commits in the last 90 days.

Generated by errors-fix · 1.9K AIC · ⌖ 34.5 AIC · ⊞ 70.8K ·

)

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

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.

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 13, 2026 16:48
@vs-code-engineering vs-code-engineering Bot enabled auto-merge (squash) July 13, 2026 16:48
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 error occurred: {"type":"networkError","reason":"Please check your fire...

2 participants