Skip to content

fix(agents): do not misclassify client-disconnect abort as run timeout#90936

Merged
clawsweeper[bot] merged 2 commits into
openclaw:mainfrom
openperf:fix/90764-external-abort-timeout-misclassification
Jun 15, 2026
Merged

fix(agents): do not misclassify client-disconnect abort as run timeout#90936
clawsweeper[bot] merged 2 commits into
openclaw:mainfrom
openperf:fix/90764-external-abort-timeout-misclassification

Conversation

@openperf

@openperf openperf commented Jun 6, 2026

Copy link
Copy Markdown
Member

Summary

  • Problem: Issue [2026.6.2-beta.1] Embedded agent runs abort at ~180s wall-clock regardless of agent/provider timeoutSeconds #90764 reports that embedded agent runs abort at ~165–180 s wall-clock regardless of agents.defaults.timeoutSeconds or models.providers.*.timeoutSeconds. The run exits with "Request timed out before a response was generated." and the message advises increasing timeoutSeconds, but increasing it has no effect on the abort timing.
  • Root Cause: onAbort and onExternalAbortSignal in src/agents/embedded-agent-runner/run/attempt.ts call isTimeoutError(reason) on the abort-signal reason to decide whether to set timedOut = true. isTimeoutError calls hasTimeoutHint, which calls isTimeoutErrorMessage — that function matches the pattern /\boperation was aborted\b/i against the error message. AbortController.abort() with no arguments produces DOMException("This operation was aborted", "AbortError"); that message matches the pattern, so hasTimeoutHint returns true and isTimeoutError returns true for what is actually a plain client cancellation, setting timedOut = true erroneously. watchClientDisconnect in src/gateway/http-common.ts calls abortController.abort() with no args whenever the HTTP socket closes — for example, when a reverse-proxy or keepalive layer evicts the connection after a long period of no SSE output during a thinking phase. This fires params.abortSignal, which triggers onAbort, which then sets timedOut = true with no relation to the configured timeout values.
  • Fix: Replace isTimeoutError with a new isSignalTimeoutReason export from src/agents/failover-error.ts. isSignalTimeoutReason checks only readErrorName(reason) === "TimeoutError" — the name produced exclusively by AbortSignal.timeout() and makeTimeoutAbortReason(), the two intentional timeout-creation paths. Plain AbortError (name = "AbortError") is a cancellation and returns false. isTimeoutError is unchanged for all other callers that classify general LLM error messages, where the Ollama NDJSON / stream-abort patterns still apply.
  • What changed:
    • src/agents/failover-error.ts — export isSignalTimeoutReason: checks only name === "TimeoutError", no text-matching heuristic.
    • src/agents/embedded-agent-runner/run/attempt.ts — replace isTimeoutError import and both abort-signal handler call sites (onExternalAbortSignal and onAbort) with isSignalTimeoutReason.
    • src/agents/failover-error.test.ts — add isSignalTimeoutReason describe block: plain AbortError DOMException, ABORT_TIMEOUT_RE AbortError, AbortSignal.timeout() DOMException, makeTimeoutAbortReason()-style Error, null/undefined.
  • What did NOT change (scope boundary):
    • isTimeoutError and its text-matching heuristics are unchanged; the change is scoped to the two abort-signal handler call sites.
    • Config surface unchanged (no schema, defaults, doctor migrations, or docs/reference/config).
    • Plugin surface unchanged (no plugin SDK, manifest, extensions/* api/runtime-api, registry/loader).
    • Gateway protocol unchanged.

Reproduction

  1. Configure agents.defaults.timeoutSeconds: 600 and models.providers.custom-api-anthropic-com.timeoutSeconds: 600.
  2. Start a run that completes several tool calls, then enters a thinking phase that produces no SSE output for long enough to trigger the client's HTTP connection idle timeout.
  3. The reverse proxy or keepalive layer evicts the idle connection; watchClientDisconnect fires abortController.abort() with no args.
  4. Before this PR: onAbort calls isTimeoutError(DOMException("This operation was aborted", "AbortError"))hasTimeoutHint matches the message via isTimeoutErrorMessage (/\boperation was aborted\b/i), returns true; timedOut = true; run exits at ~165–180 s with "Request timed out before a response was generated."; increasing timeoutSeconds has no effect.
  5. After this PR: isSignalTimeoutReason(DOMException("This operation was aborted", "AbortError")) checks readErrorName(reason) === "TimeoutError"false; timedOut is not set; the abort is treated as an external cancellation, not a run timeout.

Real behavior proof

Behavior addressed (#90764): after the fix, a client-disconnect abort no longer sets timedOut = true in the embedded attempt; only abort-signal reasons with name === "TimeoutError" (from AbortSignal.timeout() or makeTimeoutAbortReason()) are treated as run timeouts.

Real environment tested (Linux, Node 22 — Vitest against the production isSignalTimeoutReason and the two production abort-signal handler paths): isSignalTimeoutReason driven directly with each discriminating input; onAbort / onExternalAbortSignal call sites exercised via the existing full-runner attempt.test.ts suite.

Exact steps or command run after this patch: pnpm test src/agents/failover-error.test.ts; pnpm test src/agents/embedded-agent-runner/run/attempt.test.ts; pnpm format:check and node scripts/run-oxlint.mjs on the three changed files; pnpm tsgo.

Evidence after fix:

failover-error.test.ts   Tests  88 passed (88)
attempt.test.ts          Tests  121 passed (121)

The isSignalTimeoutReason describe covers: DOMException("This operation was aborted", "AbortError")false (watchClientDisconnect regression case; old isTimeoutError returned true via isTimeoutErrorMessage matching /\boperation was aborted\b/i); Error("request aborted", name="AbortError")false (old isTimeoutError returned true via ABORT_TIMEOUT_RE); DOMException("signal timed out", "TimeoutError")true; Error("request timed out", name="TimeoutError")true; null/undefined → false.

Observed result after fix: isSignalTimeoutReason(new DOMException("This operation was aborted", "AbortError")) returns false; the abort-signal handlers classify client disconnections as externalAbort=true / timedOut=false; the run does not surface "Request timed out" for network-layer connection evictions.

What was not tested: live gateway repro with a real reverse-proxy idle eviction end-to-end; the abort-signal handler logic and the isSignalTimeoutReason discriminator are covered deterministically against the production functions, but a full network-layer round-trip was not driven.

Risk / Mitigation

  • Risk: isSignalTimeoutReason is strictly narrower than isTimeoutError for the two affected call sites; a timeout path that passes params.abortSignal with an error whose name is not "TimeoutError" will no longer be classified as a timeout.
  • Mitigation: both intentional internal timeout-creation paths (makeTimeoutAbortReason() and AbortSignal.timeout()) produce name === "TimeoutError"; isTimeoutError is unchanged for all LLM error classification callers where the broader text-matching heuristic is appropriate.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Agent runtime
  • Tests

Linked Issue/PR

Fixes #90764

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS labels Jun 6, 2026
@clawsweeper

clawsweeper Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: passed. Reviewed June 14, 2026, 4:11 AM ET / 08:11 UTC.

Summary
The PR adds an abort-signal-specific timeout classifier, switches two embedded attempt abort handlers to it, and adds focused failover tests.

PR surface: Source +5, Tests +32. Total +37 across 3 files.

Reproducibility: yes. from source inspection and a focused Node abort-reason check, but not from a live 180-second proxy disconnect run. Current main routes a default AbortController abort reason through the broad timeout classifier used by the embedded abort handlers.

Review metrics: none identified.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Risk before merge

  • [P1] No live reverse-proxy/client-disconnect run was executed in this review; confidence comes from source inspection, Node abort-reason proof, PR tests, CI, and reporter production correlation.
  • [P2] A caller that intentionally encodes a timeout as an AbortError message instead of a TimeoutError signal reason would now be treated as cancellation, but inspected gateway timeout creators use TimeoutError.

Maintainer options:

  1. Decide the mitigation before merge
    Land the narrow signal-reason classifier after maintainer acceptance, keeping the broad provider error classifier unchanged for model/failover errors.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • No automated repair is needed; the remaining action is maintainer acceptance of the source/test proof versus requesting a live proxy-disconnect proof after the previous human-review pause.

Security
Cleared: The diff touches only TypeScript agent runtime classification and tests; it does not change dependencies, workflows, permissions, scripts, credentials, or package metadata.

Review details

Best possible solution:

Land the narrow signal-reason classifier after maintainer acceptance, keeping the broad provider error classifier unchanged for model/failover errors.

Do we have a high-confidence way to reproduce the issue?

Yes from source inspection and a focused Node abort-reason check, but not from a live 180-second proxy disconnect run. Current main routes a default AbortController abort reason through the broad timeout classifier used by the embedded abort handlers.

Is this the best way to solve the issue?

Yes. This is the best current fix shape because it narrows only abort-signal timeout detection to explicit TimeoutError reasons while preserving the broader message heuristics for provider and stream failover classification.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against d2c0d3ac9bc2.

Label changes

Label changes:

  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • remove rating: 🌊 off-meta tidepool: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.

Label justifications:

  • P1: The PR fixes a production embedded-agent workflow where client disconnects are surfaced as misleading run timeouts.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • status: 🚀 automerge armed: This PR is in ClawSweeper's automerge lane. Not applicable: The PR author has MEMBER association, so the external-contributor real behavior proof gate does not apply; the PR still provides deterministic test output and CI proof, with live proxy proof explicitly not run.
Evidence reviewed

PR surface:

Source +5, Tests +32. Total +37 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 2 8 3 +5
Tests 1 32 0 +32
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 3 40 3 +37

What I checked:

  • Repository policy read: Root AGENTS.md and the scoped agents runner AGENTS.md files were read fully; their guidance required reviewing the surrounding agent runtime, callers, sibling timeout paths, tests, and history before verdict. (AGENTS.md:1, d2c0d3ac9bc2)
  • Current main misclassification path: Current main still calls the broad isTimeoutError(reason) in both external abort handlers, so an AbortError reason can set timeout=true and timedOut=true. (src/agents/embedded-agent-runner/run/attempt.ts:1005, d2c0d3ac9bc2)
  • Client disconnect source: The gateway disconnect watcher aborts without an explicit reason, producing a plain cancellation reason rather than an intentional timeout reason. (src/gateway/http-common.ts:156, d2c0d3ac9bc2)
  • Broad timeout classifier evidence: The shared timeout classifier treats TimeoutError names and timeout-like messages as timeouts, and its message table includes the default abort text 'operation was aborted'. (src/agents/failover-error.ts:364, d2c0d3ac9bc2)
  • Runtime abort reason proof: Node reports AbortController.abort() with no reason as AbortError:This operation was aborted, while AbortSignal.timeout() reports TimeoutError:The operation was aborted due to timeout.
  • Proposed fix scope: The PR changes only the two embedded abort-signal handler call sites to isSignalTimeoutReason and adds a helper that checks readErrorName(reason) === "TimeoutError". (src/agents/failover-error.ts:376, 2708b0a37d85)

Likely related people:

  • Lellansin: Authored the merged gateway PR that made HTTP client disconnects abort active gateway turns, which is the cancellation source involved here. (role: introduced related disconnect behavior; confidence: high; commits: 86441207f69c, 069f57e9fb87, 17bd3a9fd4b9; files: src/gateway/http-common.ts, src/gateway/openresponses-http.ts, src/gateway/openai-http.ts)
  • obviyus: Merged the HTTP disconnect PR and authored its final socket-close commit, so they are a strong routing candidate for gateway disconnect semantics. (role: merger and adjacent contributor; confidence: high; commits: 731342105214, aad3bbebdd87; files: src/gateway/http-common.ts, src/gateway/openresponses-http.ts, src/gateway/openai-http.ts)
  • aaron-he-zhu: Authored a merged failover-classification PR touching src/agents/failover-error.ts and its tests, the shared classifier area this PR carefully avoids changing globally. (role: failover classifier contributor; confidence: medium; commits: 786d963783de, 983909f826f0; files: src/agents/failover-error.ts, src/agents/failover-error.test.ts)
  • altaywtf: Merged the generic provider failover classifier PR and contributed scoping commits in that area, making them relevant for classifier boundary review. (role: merger and adjacent failover contributor; confidence: medium; commits: fc74fa825392, 92ac8a1ab3fa, 983909f826f0; files: src/agents/failover-error.ts, src/agents/failover-error.test.ts)
  • steipete: Git history shows early timeout-abort failover work and recent adjacent agent-runtime changes, so this is a useful secondary routing candidate for timeout semantics. (role: failover timeout area contributor; confidence: medium; commits: ec27c813cc99, 574a5684a33e; files: src/agents/failover-error.ts, src/agents/model-fallback.ts, src/agents/embedded-agent-runner/run/attempt.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P1 High-priority user-facing bug, regression, or broken workflow. labels Jun 6, 2026
@openperf
openperf force-pushed the fix/90764-external-abort-timeout-misclassification branch 2 times, most recently from 93467c8 to 2a171ad Compare June 6, 2026 16:18
@Takhoffman

Copy link
Copy Markdown
Contributor

@clawsweeper automerge

@clawsweeper

clawsweeper Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🦞✅
ClawSweeper merged this PR after the passing review.

Source: clawsweeper[bot]
Feedback: structured ClawSweeper verdict: pass (sha=2708b0a37d85bca33cb28d5beb9d16f20fd08c2c)
Merge status: merged by ClawSweeper automerge
Merged at: 2026-06-15T02:38:48Z
Merge commit: fd80e0dd6be6

What merged:

  • The PR adds an abort-signal-specific timeout classifier, switches two embedded attempt abort handlers to it, and adds focused failover tests.
  • PR surface: Source +5, Tests +32. Total +37 across 3 files.
  • Reproducibility: yes. from source inspection and a focused Node abort-reason check, but not from a live 180- ... ault AbortController abort reason through the broad timeout classifier used by the embedded abort handlers.

Automerge notes:

  • PR branch already contained follow-up commit before automerge: fix(agents): do not misclassify client-disconnect abort as run timeout

The automerge loop is complete.

Automerge progress:

  • 2026-06-08 01:54:54 UTC review queued 2a171ad843d9 (queued)
  • 2026-06-08 02:02:00 UTC review passed 2a171ad843d9 (structured ClawSweeper verdict: pass (sha=2a171ad843d9f968cb406c05daec6ca056ffe...)
  • 2026-06-08 02:13:04 UTC review queued 2708b0a37d85 (after repair)
  • 2026-06-15 02:34:42 UTC review passed 2708b0a37d85 (structured ClawSweeper verdict: pass (sha=2708b0a37d85bca33cb28d5beb9d16f20fd08...)
  • 2026-06-15 02:38:50 UTC merged 2708b0a37d85 (merged by ClawSweeper automerge)

@clawsweeper clawsweeper Bot added clawsweeper:automerge Maintainer opted this PR into bounded ClawSweeper-reviewed automerge rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane. and removed rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jun 8, 2026
openperf and others added 2 commits June 8, 2026 02:12
AbortController.abort() with no args produces DOMException("This operation
was aborted", "AbortError").  The onAbort / onExternalAbortSignal handlers
in attempt.ts called isTimeoutError() on that reason; isTimeoutError delegates
to hasTimeoutHint → isTimeoutErrorMessage, which matches the pattern
/\boperation was aborted\b/i (added for Ollama stream aborts), so the plain
cancellation was mis-labelled timeout=true → timedOut=true.

Because watchClientDisconnect fires abort() with no args whenever the HTTP
connection closes (e.g. reverse-proxy idle eviction after ~120s of no SSE
data), embedded agent runs reported "Request timed out before a response was
generated." regardless of agents.defaults.timeoutSeconds or
models.providers.*.timeoutSeconds — the underlying LLM call was still in its
thinking phase.

Fix: replace isTimeoutError with isSignalTimeoutReason in both abort-signal
handlers.  isSignalTimeoutReason checks only name==="TimeoutError", which is
the name produced by AbortSignal.timeout() and makeTimeoutAbortReason().  It
never matches plain AbortError, so client disconnections are kept as
externalAbort=true / timeout=false.

Fixes openclaw#90764
@clawsweeper
clawsweeper Bot force-pushed the fix/90764-external-abort-timeout-misclassification branch from 2a171ad to 2708b0a Compare June 8, 2026 02:13
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. clawsweeper:human-review Needs maintainer review before ClawSweeper can continue and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jun 8, 2026
@clawsweeper

clawsweeper Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🦞✅
ClawSweeper is pausing this repair loop for human review.

Source: clawsweeper[bot]
Reason: - Review did not complete, so no work-lane recommendation was made. (sha=2708b0a37d85bca33cb28d5beb9d16f20fd08c2c)

Why human review is needed:
ClawSweeper found a blocker that should be resolved or accepted by a maintainer before the repair or automerge loop continues.

What the maintainer can do as a next step:
If the maintainer accepts the current risk and wants ClawSweeper to continue merge gates, comment @clawsweeper approve. If more work is needed, resolve the blocker first, then comment @clawsweeper automerge to re-review and continue. If automation should stay paused, leave clawsweeper:human-review in place or comment @clawsweeper stop.

I added clawsweeper:human-review and left the final call with a maintainer.

@reginaldomarcilon

Copy link
Copy Markdown

Hi @vincentkoc, @Takhoffman — could a maintainer take a look at this merge when you have a moment?

We're hitting this exact bug on ~5 production user pods running [email protected]. Pattern matches the diagnosis here precisely: reverse-proxy idle eviction (~120-180s no SSE data) triggers AbortController.abort() with no args, gets misclassified as a run timeout, embedded agent runs surface "Request timed out before a response was generated." even though agents.defaults.timeoutSeconds: 600 is configured. Affected users perceive it as the agent forgetting context mid-conversation.

Status checks look clean, mergeStateStatus: CLEAN, automerge was armed on 2026-06-08. Anything blocking landing this?

Happy to share redacted server logs from our cluster confirming the exact failure mode if useful.

cc @openperf — thanks for the fix!

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. clawsweeper:human-review Needs maintainer review before ClawSweeper can continue labels Jun 15, 2026
@clawsweeper
clawsweeper Bot merged commit fd80e0d into openclaw:main Jun 15, 2026
189 of 195 checks passed
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 15, 2026
openclaw#90936)

Summary:
- The PR adds an abort-signal-specific timeout classifier, switches two embedded attempt abort handlers to it, and adds focused failover tests.
- PR surface: Source +5, Tests +32. Total +37 across 3 files.
- Reproducibility: yes. from source inspection and a focused Node abort-reason check, but not from a live 180- ... ault AbortController abort reason through the broad timeout classifier used by the embedded abort handlers.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(agents): do not misclassify client-disconnect abort as run timeout

Validation:
- ClawSweeper review passed for head 2708b0a.
- Required merge gates passed before the squash merge.

Prepared head SHA: 2708b0a
Review: openclaw#90936 (comment)

Co-authored-by: openperf <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
vincentkoc pushed a commit that referenced this pull request Jun 15, 2026
#90936)

Summary:
- The PR adds an abort-signal-specific timeout classifier, switches two embedded attempt abort handlers to it, and adds focused failover tests.
- PR surface: Source +5, Tests +32. Total +37 across 3 files.
- Reproducibility: yes. from source inspection and a focused Node abort-reason check, but not from a live 180- ... ault AbortController abort reason through the broad timeout classifier used by the embedded abort handlers.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(agents): do not misclassify client-disconnect abort as run timeout

Validation:
- ClawSweeper review passed for head 2708b0a.
- Required merge gates passed before the squash merge.

Prepared head SHA: 2708b0a
Review: #90936 (comment)

Co-authored-by: openperf <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
(cherry picked from commit fd80e0d)
wangmiao0668000666 pushed a commit to wangmiao0668000666/openclaw that referenced this pull request Jun 17, 2026
openclaw#90936)

Summary:
- The PR adds an abort-signal-specific timeout classifier, switches two embedded attempt abort handlers to it, and adds focused failover tests.
- PR surface: Source +5, Tests +32. Total +37 across 3 files.
- Reproducibility: yes. from source inspection and a focused Node abort-reason check, but not from a live 180- ... ault AbortController abort reason through the broad timeout classifier used by the embedded abort handlers.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(agents): do not misclassify client-disconnect abort as run timeout

Validation:
- ClawSweeper review passed for head 2708b0a.
- Required merge gates passed before the squash merge.

Prepared head SHA: 2708b0a
Review: openclaw#90936 (comment)

Co-authored-by: openperf <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
crh-code pushed a commit to crh-code/openclaw that referenced this pull request Jun 18, 2026
openclaw#90936)

Summary:
- The PR adds an abort-signal-specific timeout classifier, switches two embedded attempt abort handlers to it, and adds focused failover tests.
- PR surface: Source +5, Tests +32. Total +37 across 3 files.
- Reproducibility: yes. from source inspection and a focused Node abort-reason check, but not from a live 180- ... ault AbortController abort reason through the broad timeout classifier used by the embedded abort handlers.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(agents): do not misclassify client-disconnect abort as run timeout

Validation:
- ClawSweeper review passed for head 2708b0a.
- Required merge gates passed before the squash merge.

Prepared head SHA: 2708b0a
Review: openclaw#90936 (comment)

Co-authored-by: openperf <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
badgerbees pushed a commit to badgerbees/openclaw that referenced this pull request Jul 8, 2026
openclaw#90936)

Summary:
- The PR adds an abort-signal-specific timeout classifier, switches two embedded attempt abort handlers to it, and adds focused failover tests.
- PR surface: Source +5, Tests +32. Total +37 across 3 files.
- Reproducibility: yes. from source inspection and a focused Node abort-reason check, but not from a live 180- ... ault AbortController abort reason through the broad timeout classifier used by the embedded abort handlers.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(agents): do not misclassify client-disconnect abort as run timeout

Validation:
- ClawSweeper review passed for head 2708b0a.
- Required merge gates passed before the squash merge.

Prepared head SHA: 2708b0a
Review: openclaw#90936 (comment)

Co-authored-by: openperf <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
chovizzz added a commit to chovizzz/openclaw that referenced this pull request Jul 16, 2026
…penclaw#90936)

Add isSignalTimeoutReason and use it in pi-embedded attempt abort handling
so plain AbortError disconnects are not treated as run timeouts.

Co-authored-by: Cursor <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling clawsweeper:automerge Maintainer opted this PR into bounded ClawSweeper-reviewed automerge P1 High-priority user-facing bug, regression, or broken workflow. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: XS status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[2026.6.2-beta.1] Embedded agent runs abort at ~180s wall-clock regardless of agent/provider timeoutSeconds

3 participants