OpenClaw’s Same-Day Failover PRs Define the Difference Between Provider Failure and Local Tool Failure

OpenClaw’s Same-Day Failover PRs Define the Difference Between Provider Failure and Local Tool Failure

Fallback sounds simple until it starts hiding the wrong failure. Two OpenClaw PRs opened within 19 seconds of each other on June 21 make the distinction unusually clear: rotate providers when the provider fails, but do not burn fallback capacity when the local runtime broke. That line matters because agent systems now combine remote model calls, local shell execution, tool-result protocols, approval gates, and child sessions. “Try another model” is not a universal recovery strategy. Sometimes it is just a more expensive way to misunderstand the incident.

PR #95542 addresses one side of the boundary. Issue #95519 reports OpenClaw 2026.6.8 ending a turn on the primary provider after receiving a structured payload shaped like {"error":{"message":"Upstream request failed","type":"upstream_error","param":"","code":null}}. The configured fallback models did not run, and no model.fallback_step events appeared. PR #95542 changes 4 files, with 78 additions and 6 deletions, mapping structured errorType: "upstream_error" and JSON error.type: "upstream_error" to the existing server_error failover reason.

That is the boring-correct fix. If the upstream provider says the upstream failed, the agent runtime should treat it as provider-class failure and advance through the configured fallback chain. Operators configure fallback models precisely for this category: transient provider errors, overload, rate limits, server failures, and similar remote failures where another model endpoint may succeed without changing the local task state.

Local tool failures are not model failures

PR #95543 handles the opposite case. Issue #95474 reports Codex native bash hangs being reaped as synthetic missing_tool_result errors, then misclassified as unclassified. That misclassification caused OpenClaw to fall back from openai/gpt-5.4 to anthropic/claude-opus-4-8, even though the root problem was a local tool execution failure. Another model cannot make a hung shell command retroactively return the missing tool result. It can only spend more money and potentially obscure the original boundary violation.

PR #95543 changes 3 files, with 105 additions and 6 deletions, teaching the non-provider runtime coordination guard to recognize Codex missing_tool_result sentinels before generic unknown-error fallback consumes candidates. The proof is clean: with primary openai/gpt-5.4 and fallback anthropic/claude-opus-4-8, the observed path stayed on openai/gpt-5.4, rethrew the original error, and recorded fallbackAttempted: false.

This is the kind of fix that makes cost controls and debugging better at the same time. If a local tool hung, the operator needs to know that the local tool hung. Routing to a backup model converts a runtime incident into an LLM comparison exercise, which is exactly the wrong abstraction. Worse, it may change the task plan after partial local effects have already occurred. For coding agents with shell access, that is not harmless. The filesystem, process table, and approval state are shared reality; the second model enters after the first one already changed the room.

There is a related sibling PR, #95537, that broadens transient payload reasons including rate_limit, overloaded, server_error, and timeout. Reviewer NianJiuZst reportedly preferred #95542’s canonical approach because it uses parsed structured error information rather than brittle substring matching. That review point is the whole architecture lesson. Runtime failover should be typed, not vibes-based. An error classifier that scrapes strings will eventually confuse “provider failed” with “tool protocol violated” or “approval refused.”

For practitioners, the actionable checklist is simple. First, instrument fallback with reason codes, not just model names. You should be able to answer: did this turn fallback because of rate limit, timeout, provider server error, local tool coordination, schema mismatch, approval refusal, or user cancellation? Second, treat fallback as a budgeted resource. Every unnecessary fallback spends tokens, latency, and sometimes higher-tier model capacity. Third, do not allow cross-provider fallback to paper over local side effects. If a shell tool timed out after partially writing files, the next model needs a truthful recovery state, not a clean rerun fantasy.

The broader industry keeps selling fallback as reliability. It can be, but only when the failure taxonomy is honest. Provider failure is a routing problem. Local tool failure is a control-plane problem. Approval refusal is a human-boundary outcome. Protocol mismatch is an integration bug. If an agent platform collapses all of those into “try Claude next,” it has not built resilience. It has built a very polite incident obfuscator.

OpenClaw’s same-day PR pair is useful because it draws the line in code. Rotate when the upstream provider is at fault. Stop and surface the error when the local runtime is at fault. That is less magical than automatic fallback everywhere, which is why it is more likely to work in production.

This is also where observability has to catch up. Dashboards that show only “fallback used” are no longer enough. Teams need provider-class, runtime-class, approval-class, and user-class failures separated in logs and metrics. Otherwise every outage becomes folklore: someone remembers that a backup model ran, nobody remembers whether it should have, and the same local-tool bug survives under a nicer completion.

Sources: OpenClaw PR #95542, OpenClaw PR #95543, OpenClaw issue #95519, OpenClaw issue #95474, OpenClaw PR #95537