Description
When the Anthropic API returns 429 (rate limit) and all retries are exhausted, the Gateway saves the assistant message containing tool_use blocks to the session .jsonl file without a corresponding tool_result block. This creates an invalid message history that permanently blocks the session — every subsequent API request fails with:
messages.N: `tool_use` ids were found without `tool_result` blocks immediately after: execXXX
The session remains dead until the Gateway is restarted (creating a new session).
Steps to Reproduce
- Agent (Claude Opus) calls a tool (e.g.,
exec)
- API rate limit (429) is hit during the request
- Gateway retries multiple times (observed 20 retries in ~3 minutes)
- All retries fail → Gateway saves the assistant message with
tool_use to .jsonl
tool_result is never written (the tool was never executed)
- Next heartbeat/request → Anthropic API rejects with 400
tool_use without tool_result
- Session is permanently broken
Observed Behavior (Feb 25, 2026)
22:11:35-22:14:05 — 20x rate limit retries (same runId)
22:26:33 — First 400 error (orphan tool_use: exec17720470437771)
22:26-00:49 — 7 consecutive heartbeats, all failed with same error
01:05 — Gateway restart → new session (workaround, not fix)
Additional context: Gateway was in a crash-loop (634 restarts) due to an unrecognized config key (cron.fleet-monitor), which likely contributed to the rate limit being hit.
Expected Behavior
If all rate limit retries are exhausted:
- The orphan
tool_use assistant message should not be persisted to the session .jsonl
- OR a synthetic
tool_result with an error message should be appended (e.g., {"type": "tool_result", "content": "Rate limit exceeded, tool was not executed"})
Workaround
We built a cron-based session-healer plugin that:
- Detects the error pattern in Gateway logs
- Finds the orphan
tool_use line in .jsonl by ID
- Surgically removes it + injects a recovery message
- Escalates (retry → remove compaction summary → rotate session)
Environment
- OpenClaw: 2026.2.23 (b817600)
- Model: anthropic/claude-opus-4-6
- OS: Ubuntu Linux 6.8.0
- Node: v22.22.0
Description
When the Anthropic API returns 429 (rate limit) and all retries are exhausted, the Gateway saves the assistant message containing
tool_useblocks to the session.jsonlfile without a correspondingtool_resultblock. This creates an invalid message history that permanently blocks the session — every subsequent API request fails with:The session remains dead until the Gateway is restarted (creating a new session).
Steps to Reproduce
exec)tool_useto.jsonltool_resultis never written (the tool was never executed)tool_use without tool_resultObserved Behavior (Feb 25, 2026)
Additional context: Gateway was in a crash-loop (634 restarts) due to an unrecognized config key (
cron.fleet-monitor), which likely contributed to the rate limit being hit.Expected Behavior
If all rate limit retries are exhausted:
tool_useassistant message should not be persisted to the session.jsonltool_resultwith an error message should be appended (e.g.,{"type": "tool_result", "content": "Rate limit exceeded, tool was not executed"})Workaround
We built a cron-based
session-healerplugin that:tool_useline in.jsonlby IDEnvironment