Skip to content

[Bug]: Generic "An unknown error occurred" stream errors don't trigger model fallback for non-Anthropic providers #71620

Description

@mattcproctor

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

Provider gate in isAnthropicGenericUnknownError (dist/errors-CJULmF31.js:423) prevents the configured model fallback chain from rotating when non-Anthropic providers hit the generic "An unknown error occurred" stream-error path; the literal error string is surfaced to end users.

Steps to reproduce

  1. Configure agents.defaults.model.primary = "google/gemini-2.5-flash" with non-empty agents.defaults.model.fallbacks.
  2. Send the gateway an agent request that causes the Gemini stream to end with stopReason: "error".
  3. Observe the user-facing reply contains the literal text An unknown error occurred. Journal shows [agent/embedded] embedded run agent end ... isError=true ... provider=google error=An unknown error occurred rawError=An unknown error occurred with no fallback rotation attempted.

Expected behavior

Configured fallback models are tried in sequence, matching the behavior already implemented for provider === "anthropic" (classified as timeout and routed through the failoverFailure path in dist/pi-embedded-runner-*.js:7340).

Actual behavior

classifyFailoverReason returns null for non-Anthropic providers because the gate at line 423 is isProvider(provider, "anthropic") && .... isFailoverAssistantError returns false, failoverFailure is false, fallback rotation is skipped, and the literal stream-wrapper error is returned to the user.

OpenClaw version

2026.4.15 (build 041266a)

Operating system

Ubuntu 24.04 (ARM64, Oracle Cloud)

Install method

npm global

Model

google/gemini-2.5-flash (primary); fallbacks: google/gemini-flash-latest, google/gemini-3.1-pro-preview

Provider / routing chain

openclaw -> google (direct, api_key auth profile)

Additional provider/model setup details

Standard direct Google provider via api_key auth profile. No proxy/router layer. Fallbacks configured under agents.defaults.model.fallbacks.

Logs, screenshots, and evidence

Logs, screenshots, and evidence (in the shell-rendered block):
  2026-04-25T13:43:48.879+00:00 [whatsapp] Inbound message (145 chars)
  2026-04-25T13:43:55.770+00:00 [gateway] cron: job updated
  2026-04-25T13:44:00.035+00:00 [agent/embedded] embedded run agent end:
    runId=<redacted> isError=true model=gemini-2.5-flash provider=google
    error=An unknown error occurred rawError=An unknown error occurred

  Code references in installed dist/:
  - errors-CJULmF31.js:423  (provider-gated branch in isAnthropicGenericUnknownError)
  - errors-CJULmF31.js:458  (call site in classifyFailoverClassificationFromMessage)
  - anthropic-vertex-stream-BpkPWKP9.js:4720, 6211, 6349
      (provider-agnostic stream wrapper that throws the generic
       Error("An unknown error occurred") for any provider when
       stopReason === "aborted" | "error")
  - pi-embedded-runner-DN0VbqlW.js:7340
      (failoverFailure branch that never fires due to classification gap)

Impact and severity

Affected: deployments using a non-Anthropic primary model with configured fallbacks (Google Gemini in our case).
Severity: High for user-facing channels — raw error text surfaces to end users instead of the fallback response.
Frequency: Consistent when the Gemini stream ends in stopReason === "error". Observed in production 2026-04-25 13:44 UTC; defeats the purpose of having fallbacks configured.
Consequence: configured fallback chain is silently bypassed.

Additional information

Suggested fix: rename isAnthropicGenericUnknownError → isGenericUnknownStreamError and drop the isProvider(provider, "anthropic") && gate. Alternative is to fix upstream by having the streaming wrapper throw a provider-tagged error string so each provider's classifier can pattern-match its own variant. Hotfix applied locally on 2026.4.15 (one-line patch removing the gate); gateway restarted cleanly and channels reconnected normally.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions