Skip to content

Timeout (AbortError) does not trigger fallback model chain #95

@Dazee-daze

Description

@Dazee-daze

Summary

When an LLM request hits the hard timeout (AbortError), the extension throws an error outside the fallback for loop, causing the full fallback model chain to be silently skipped. No fallback model is ever tried on timeout — only on provider errors (4xx/5xx).

Expected Behavior

On AbortError (request timeout), the loop should continue to the next model in the fallback chain — the same behavior that occurs when a provider returns a 4xx/5xx error.

Actual Behavior

The throw in the AbortError handler (around proxy.ts line 1102) exits the try/catch and the entire for loop. The full fallback chain configured in openclaw.json is never invoked on timeouts.

Steps to Reproduce

  1. Configure a multi-model fallback chain in openclaw.json
  2. Send a high-complexity request (long context + image attachments) that exceeds the DEFAULT_REQUEST_TIMEOUT_MS threshold
  3. Observe: the primary model times out, no fallback model is attempted, the request fails with a hard FailoverError

Root Cause

In proxy.ts, the AbortError catch block throws unconditionally:

if (err instanceof Error && err.name === "AbortError") throw new Error(`Request timed out...`)

This throw exits the fallback for loop entirely instead of continue-ing to the next model.

Suggested Fix

Move the timeout handler inside the fallback loop so it can continue to the next model:

// Inside the fallback for loop
if (err instanceof Error && err.name === "AbortError") {
  console.warn(`Model ${modelId} timed out, trying next fallback...`);
  continue; // instead of throw
}

Environment

  • OpenClaw gateway with ClawRouter extension
  • Fallback chain: claude-max/claude-sonnet-4claude-max/claude-opus-4openai-codex/gpt-5.3-codex → (additional fallbacks)
  • Hard timeout: DEFAULT_REQUEST_TIMEOUT_MS (~180–300s)
  • Observed: 7+ timeout failures in a single session, all skipping the fallback chain

Impact

Users relying on fallback chains for reliability get hard failures on timeout instead of automatic model fallover. This defeats the purpose of the fallback configuration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions