Skip to content

user-switched model has no fallback chain, causing session deadlock on provider outage #84865

Description

@njuboy11

Summary

When a user manually switches the active model (e.g., /model deepseek/deepseek-v4-pro), OpenClaw disables the fallback chain entirely. If that model becomes unavailable (provider 503, timeout, 5xx), the session deadlocks — the Gateway retries the same model in a loop with no recovery path.

Root Cause

resolveEffectiveModelFallbacks() in src/agents/agent-scope.ts returns [] when modelOverrideSource === "user". The function treats any non-auto override as a signal to disable fallbacks, on the assumption that the user explicitly chose their model and no substitution should be made.

The downstream effect: persistFallbackCandidateSelection() in the agent runner also returns early for user-switched models, preventing fallback persistence. Between empty fallbacks and blocked persistence, the session has zero recovery options.

Real Incident Data (2026-05-21, 14:00–14:14 CST)

Timeline

Time (CST) Event
13:43 User switches to deepseek/deepseek-v4-pro
13:46–14:00 Normal conversation with 42 tool calls
14:00:23 DeepSeek v4-pro model call hangs (120s idle timeout)
14:02:28 Gateway logs: stalled session, LLM idle timeout (120s): no response from model
14:07 User sends follow-up message — system cannot process (v4-pro still hung)
14:08:06 Context compaction fails: v4-pro timeout (61s), v4-flash file_lock_stale
14:10:15 Another deepseek-v4-pro call times out (120s)
14:10:36 User force-restarts Gateway (SIGTERM)
14:12:09 After restart, compaction fails on v4-pro (timeout)
14:12:12 Compaction on v4-flash fails: provider_error_5xx
14:13:12 Another compaction fails on v4-flash: provider_error_5xx
14:13:58 Session finally aborted after ~14 minutes of stall

Provider error evidence

Confirmed DeepSeek outage at the time:

503 Service is too busy. We advise users to temporarily switch to alternative LLM API service providers.

Gateway diagnostic logs

13:59:25 [diagnostic] long-running session: age=577s queueDepth=1 reason=queued_behind_active_work
14:02:25 [diagnostic] stalled session: age=757s reason=active_work_without_progress
14:02:28 [agent/embedded] embedded run failover decision: decision=surface_error reason=timeout
  rawError="LLM idle timeout (120s): no response from model" fallbackConfigured=false

The fallbackConfigured=false flag confirms the session had no fallback path for the user-switched model.

Proposed Fix

In resolveEffectiveModelFallbacks(): when modelOverrideSource === "user", return the agent's configured fallbacks instead of an empty array. This gives user-switched models a per-call recovery path. The existing persistFallbackCandidateSelection guard ensures the fallback selection is NOT persisted to session state, so the user's model preference is preserved for the next message.

Related

  • PR: #TBD (to be linked)

Metadata

Metadata

Assignees

Labels

P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.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.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.impact:crash-loopCrash, hang, restart loop, or process-level availability failure.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

Type

No type

Fields

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions