Skip to content

fix: mark 'Language model unavailable' as expected chat error (fixes #326356)#326357

Open
vs-code-engineering[bot] wants to merge 1 commit into
mainfrom
fix/chatagent-lm-unavailable-expected-451a315133162656
Open

fix: mark 'Language model unavailable' as expected chat error (fixes #326356)#326357
vs-code-engineering[bot] wants to merge 1 commit into
mainfrom
fix/chatagent-lm-unavailable-expected-451a315133162656

Conversation

@vs-code-engineering

Copy link
Copy Markdown
Contributor

Summary

The chatAgentError telemetry bucket chatagenterror-Language model unavailable fires whenever ExtHostChatAgents2.getModelForRequest cannot resolve a language model for a chat request — thrown from $invokeAgent (and $detectChatParticipant). This is an expected operational condition (the user is not signed in, or no chat models have been contributed yet), not a code bug, but it was thrown as a generic Error and therefore published to error telemetry as noise. The fix marks it as a ChatExpectedError so the existing suppression path keeps it out of chatAgentError telemetry while still surfacing the user-facing message.

Fixes #326356
Recommended reviewer: @bryanchen-d

Culprit Commit

Field Value
Commit Not identified — pre-existing / re-bucketing
Author n/a
PR n/a
Message n/a
Why The throw new Error('Language model unavailable') in getModelForRequest is a long-standing pattern. The isExpectedError / ChatExpectedError suppression mechanism was added later (3727d0ce, "add isExpectedError flag to suppress expected agent errors from telemetry", by @bryanchen-d, 2026-04-27). This throw was simply never opted into that mechanism, so it continued surfacing as a chatAgentError bucket. No single regression commit introduced the error path.

No culprit commit — this is a pre-existing expected-error condition that was never registered with the ChatExpectedError telemetry-suppression channel.

Code Flow

sequenceDiagram
    participant Agent as Chat request
    participant Invoke as extHostChatAgents2.$invokeAgent
    participant Producer as getModelForRequest
    participant Main as mainThreadChatAgents2

    Agent->>Invoke: invoke agent
    Invoke->>Producer: getModelForRequest(request, extension)
    Note over Producer: ⚠️ No user-selected model and<br/>getDefaultLanguageModel() returns undefined<br/>(user not signed in / no models)
    Producer-->>Invoke: throw new Error('Language model unavailable')
    Note over Invoke: 💥 Generic Error → errorCallstack packed,<br/>isExpectedError NOT set
    Invoke->>Main: rpcResult { errorCallstack, errorName }
    Note over Main: publishes chatAgentError telemetry<br/>(bucket: chatagenterror-Language model unavailable)
Loading

Affected Files

File Role Evidence
src/vs/workbench/api/common/extHostChatAgents2.ts root cause / producer L948-L949 (pre-fix): if (!model) { throw new Error('Language model unavailable'); } — expected condition thrown as generic Error
src/vs/workbench/api/common/extHostChatAgents2.ts crash site L900/L950 (from shipped-commit stack): getModelForRequest / $invokeAgent
src/vs/workbench/api/browser/mainThreadChatAgents2.ts telemetry emitter L380-L397: if (rpcResult?.errorCallstack && !rpcResult.errorDetails?.isExpectedError) { ... publicLogError2('chatAgentError', ...) } — suppresses when isExpectedError is set

Repro Steps

  1. Launch the Agents window / chat in a profile that is not signed in to Copilot (or that has no contributed chat models).
  2. Send a chat request to an agent, or trigger participant detection.
  3. getModelForRequest resolves no user-selected model and getDefaultLanguageModel() returns undefined, so throw new Error('Language model unavailable') fires.
  4. Before this fix, the generic error is packed with a callstack and published as the chatAgentError telemetry event, producing the chatagenterror-Language model unavailable bucket.

How the Fix Works

Chosen approachsrc/vs/workbench/api/common/extHostChatAgents2.ts, getModelForRequest: the fix is applied at the data producer (where the invalid/expected state is first detected), not at the crash site or in a downstream try/catch. Instead of throwing a generic Error, the "no model available" case now throws an error whose name is set to ChatExpectedError. $invokeAgent already maps e.name === 'ChatExpectedError' to errorDetails.isExpectedError = true, and mainThreadChatAgents2 already skips publishing the chatAgentError event when that flag is set (the existing suppression channel added for rate-limit / quota / connectivity / "cloud agent not enabled" conditions). This removes the bucket from error telemetry while preserving the user-facing message and the logService.error log entry — no logging is removed and no error is swallowed in a try/catch.

This is the intended use of the ChatExpectedError mechanism: a genuinely expected, user-actionable operational condition opts out of bug telemetry rather than being silenced.

Alternatives considered:

  • Gating the logService.error(e, ...) call or the chatAgentError emission on the message string 'Language model unavailable' — rejected because string-matching in the consumer is brittle and puts the decision in the wrong place; the producer already knows the condition is expected.
  • Wrapping the getModelForRequest call in a try/catch that returns a benign result — rejected because it hides the condition from the user-facing error surface and masks the state instead of classifying it.

Recommended Owner

@bryanchen-d — owner of the chatAgentError telemetry event (owner: 'bryanchen-d' in mainThreadChatAgents2.ts) and author of the isExpectedError / ChatExpectedError suppression mechanism this fix uses. Active VS Code team member; already assigned to the issue.

Generated by errors-fix · 2K AIC · ⌖ 34.2 AIC · ⊞ 71K ·

Copilot AI review requested due to automatic review settings July 17, 2026 15:01

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 17, 2026 15:02
@vs-code-engineering
vs-code-engineering Bot enabled auto-merge (squash) July 17, 2026 15:02
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] chatagenterror-Language model unavailable

2 participants