mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-20 17:41:33 -06:00
3f1f30d939
Debug capture clones every response and reads the clone under a byte cap, but with no bound on how long it waits between chunks. A remote that sends headers and one chunk and then goes silent leaves that read outstanding forever — and because clone() tees the body, a branch settles its cancellation only once both branches cancel or the source reaches EOF. So the caller's own cancellation, and the guarded transport release that follows it, end up waiting on a diagnostic read of a body nobody wants. Read through the shared idle-bounded reader instead. On timeout it issues the branch cancel fire-and-forget and throws, which is what lets the tee settle; capture then records the exchange as metadata with bodyCapture "stalled", alongside the existing too-large and unavailable cases. A stalled remote must not turn a diagnostic read into a failure of the request being observed. That helper also rejects when the read itself fails, and only the deadline is capture's decision to make: a reset or aborted stream is the exchange failing and still has to reach the error handler, so capture supplies its own timeout error and rethrows anything else. The response wrapper's cancel-then-release ordering is deliberate, pinned by its own test, and stays untouched. Co-authored-by: Peter Steinberger <steipete@gmail.com>