Skip to content

[Bug]: Behavior bug (incorrect output/state without crash) #95574

Description

@riazrahaman

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

When an Ollama (or other harnessOwnsTransport) provider times out during a prompt, OpenClaw surfaces "LLM request timed out." directly to the user and never attempts the configured fallbacks list.

Steps to reproduce

  1. Steps to reproduce

Configure a local Ollama model as primary with at least one fallback:
"model": {
"primary": "ollama/qwen3.6:latest",
"fallbacks": [
"ollama/gemma4:26b",
"openrouter/google/gemini-2.5-flash",
"claude-cli/claude-sonnet-4-6"
]
}

  1. Send a message that causes the Ollama request to time out (slow hardware, large context, or low timeoutSeconds).
  2. Observe the reply: "LLM request timed out." — no fallback model is tried.

Expected behavior

When a provider fails with a timeout and model.fallbacks is configured, OpenClaw should attempt the next model in the fallback chain, identical to its behavior on auth or billing failures.

Actual behavior

OpenClaw immediately surfaces "LLM request timed out." to the user. Trajectory records finalStatus: error, timedOut: true, promptErrorSource: prompt with no fallback attempt in traceAttempts.

Root cause traced to resolveRunFailoverDecision in embedded-agent-CpxCz9I4.js:

// Lines 711–714 — stage === "prompt" branch
if (params.harnessOwnsTransport && params.failoverReason === "timeout") return {
action: "surface_error", // ← fires before the fallbackConfigured check below
reason: params.failoverReason
};
// Line 719 — never reached when harnessOwnsTransport && timeout:
if (params.fallbackConfigured && params.failoverFailure && ...) return { action: "fallback_model" };

harnessOwnsTransport is true for all direct-API providers (Ollama, OpenRouter). The early return at line 711 preempts the fallbackConfigured guard entirely, so the fallback chain is never entered regardless of configuration.

The same logic blocks the assistant-stage path in shouldRotateAssistant (line 681):

if (params.harnessOwnsTransport && (timeoutFailure || params.failoverReason === "timeout")
&& !isConcreteNonTimeoutAssistantFailure(params)) return false; // assistantShouldRotate = false

The result-level classifier (result-fallback-classifier-CgsLfRqx.js) also misses it as a secondary safety net — classifyBusinessDenialErrorPayloadReason maps "timeout" to null (only "auth", "auth_permanent", "billing" are handled), and !isGpt5ModelId(model) gates out non-GPT-5 models before any catch-all.

Suggested minimal fix — add && !params.fallbackConfigured to line 711:

if (params.harnessOwnsTransport && params.failoverReason === "timeout" && !params.fallbackConfigured) return {
action: "surface_error",
reason: params.failoverReason
};

This preserves the existing surface_error behavior when no fallback is configured, while allowing the fallbackConfigured check at line 719 to fire when one is.

OpenClaw version

2026.6.5

Operating system

macOS 25.5.0

Install method

Homebrew (npm global via Homebrew)

Model

ollama/qwen3.6:latest

Provider / routing chain

openclaw → Ollama (http://localhost:11434) — harnessOwnsTransport: true

Additional provider/model setup details

Full fallback chain at time of failure:
primary: ollama/qwen3.6:latest
fallbacks: ollama/gemma4:26b
openrouter/google/gemini-2.5-flash
openrouter/meta-llama/llama-3.3-70b-instruct
claude-cli/claude-sonnet-4-6

models.providers.ollama.baseUrl: http://localhost:11434. No per-session model override was in effect for the failing session (override was on a different session key).

Logs, screenshots, and evidence

# Trajectory event — session 3a0c7cf0-b002-45d1-b3b7-cc14cd6d47e5
# File: ~/.openclaw/agents/main/sessions/3a0c7cf0-b002-45d1-b3b7-cc14cd6d47e5.trajectory.jsonl

ts:                2026-06-21T11:41:58.340Z
type:              model.completed
provider:          ollama
model:             qwen3.6:latest
timedOut:          true
idleTimedOut:      false
finalStatus:       error
promptErrorSource: prompt

No fallback_model entry appears in traceAttempts for this session. The session ended immediately after the timeout with finalStatus: error.

Impact and severity

  • Affected: Any user running a local Ollama primary model with a cloud fallback chain, triggered via Telegram, cron jobs, or direct chat
  • Severity: High — the entire purpose of the fallback chain (offline/overloaded local model → cloud fallback) is silently defeated
  • Frequency: Reproducible every time Ollama times out on a full request (non-idle timeout)
  • Consequence: User sees a hard error and must manually retry or /new; automated cron jobs silently fail without attempting any fallback

Additional information

This is a related but distinct bug from the claude-cli out-of-credits fallback issue (where GENERIC_EXTERNAL_RUN_FAILURE_TEXT is emitted as visible text, causing hasVisibleAgentPayload() to return true and short-circuit the result-level classifier). That bug affects harnessOwnsTransport: false providers; this bug affects harnessOwnsTransport: true providers.

The idleTimedOut case (model silent, watchdog fires) is partially handled by the same-model retry at line 840 (allowSameModelIdleTimeoutRetry), but only when idleTimedOut = true. A full request timeout (timedOut: true, idleTimedOut: false) has no fallback path at all.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.bugSomething isn't workingbug:behaviorIncorrect behavior without a crashclawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions