fix(agents): classify stream abort errors as transient for fallback rotation#95632
fix(agents): classify stream abort errors as transient for fallback rotation#95632ruomuxydt wants to merge 3 commits into
Conversation
…otation The HTTP/fetch layer emits "This operation was aborted" when a streaming connection drops mid-response (e.g. Bedrock Converse after ~6 min on large payloads). This error was not matched by any failover classification pattern, so the session died with no retry and no fallback attempt. Add isStreamAbortErrorMessage to classify these errors as "timeout" (transient), so the configured fallback chain rotates instead of surfacing the bare abort string to the user. Fixes openclaw#87876
|
Thanks for the context here. I swept through the related work, and this is now duplicate or superseded. This PR is superseded: current main already has the shared stream-abort timeout matcher and a stronger model-fallback regression proving provider-side Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Canonical path: Keep the current main fallback behavior from the merged matcher and runtime fixes, and leave any remaining Bedrock transcript/retry work on #87876 rather than merging this classifier-only branch. So I’m closing this here and keeping the remaining discussion on #87876. Review detailsBest possible solution: Keep the current main fallback behavior from the merged matcher and runtime fixes, and leave any remaining Bedrock transcript/retry work on #87876 rather than merging this classifier-only branch. Do we have a high-confidence way to reproduce the issue? Yes for the review decision: current main source and tests show provider-side Is this the best way to solve the issue? No, this is not the best way to solve the issue now. The best fix path is the already-merged runtime fallback boundary coverage on current main, with broader Bedrock transcript/retry work left to the canonical issue if it still reproduces. Security review: Security review cleared: The diff only adds tests and a local repro script; I found no dependency, workflow, credential, permission, install, or supply-chain surface change. AGENTS.md: found and applied where relevant. What I checked:
Likely related people:
Codex review notes: model internal, reasoning high; reviewed against 0bf66ab7bdbf. |
|
@clawsweeper re-review Added real behavior proof to PR body:
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
…eout matcher Address review gap: isStreamAbortErrorMessage duplicated the existing pattern /\boperation was aborted\b/i already present in failover-matches.ts ERROR_PATTERNS.timeout. Remove the duplicate helper and its classification call. The existing isTimeoutErrorMessage already handles "This operation was aborted" through the shared timeout pattern, so the fallback chain rotates correctly for Bedrock Converse stream drops. Update test and repro to verify the shared classifier covers the stream abort case instead of testing a removed helper.
|
@clawsweeper re-review Addressed review gaps:
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
Address review gap: add classifyFailoverReason tests proving the full classification chain classifies "This operation was aborted" as "timeout", confirming the error triggers fallback rotation instead of surfacing immediately.
|
@clawsweeper re-review Addressed review gaps:
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@ruomuxydt thanks for the PR. ClawSweeper is still waiting on real behavior proof before this can move forward. Useful proof can be a screenshot, short video, terminal output, copied live output, linked artifact, or redacted logs that show the changed behavior after the fix. Please redact private tokens, phone numbers, private endpoints, customer data, and anything else sensitive. Once proof is added to the PR body or a comment, ClawSweeper or a maintainer can re-check it. |
|
ClawSweeper applied the proposed close for this PR.
|
Summary
The Bedrock Converse Streaming API silently drops connections after ~6 minutes on large payloads. The HTTP/fetch layer throws
"This operation was aborted", which the session dies with — no retry, no fallback, no transcript saved.Finding: The existing shared timeout classifier in
failover-matches.tsalready matches"operation was aborted"viaERROR_PATTERNS.timeout[171](/\boperation was aborted\b/i). The full classification chain (classifyFailoverReason) confirms the error is classified as"timeout", meaning it triggers fallback rotation — not immediate surfacing.This PR:
isStreamAbortErrorMessagehelper that was a subset of the existing shared patternChanges
src/agents/embedded-agent-helpers/errors.ts: Removed the duplicateisStreamAbortErrorMessagehelper and its classification call. The existingisTimeoutErrorMessagealready handles "This operation was aborted".src/agents/embedded-agent-helpers/errors.test.ts: Added 4 tests — (1) shared classifier matches, (2) full chain classifies as timeout, (3) embedded message classifies as timeout, (4) import stability.scripts/repro/issue-87876-stream-abort-classify.mts: Real behavior proof script.Real behavior proof
Behavior addressed: Stream abort errors ("This operation was aborted") are already classified as "timeout" by the existing shared classifier, so the fallback chain rotates for Bedrock Converse stream drops.
Real environment tested: Windows 10, Node.js v22.19.2, source tree at commit 602d9e7.
Exact steps or command run after this patch:
node --import tsx scripts/repro/issue-87876-stream-abort-classify.mtsEvidence after fix:
Observed result after fix: The existing
isTimeoutErrorMessageinfailover-matches.tsalready matches "This operation was aborted" throughERROR_PATTERNS.timeout[171]. The fullclassifyFailoverReasonchain confirms it returns "timeout". No new classifier was needed.What was not tested: Live Bedrock Converse Streaming round-trip. The finding is classification-level, verified by the shared timeout matcher and end-to-end classification tests.
Verification
Related to #87876