Skip to content

fix: clone Request inputs so retries do not reuse a consumed body - #197

Open
pouyashahrdami wants to merge 1 commit into
cloudflare:mainfrom
pouyashahrdami:fix/fetch-retry-request-body
Open

fix: clone Request inputs so retries do not reuse a consumed body#197
pouyashahrdami wants to merge 1 commit into
cloudflare:mainfrom
pouyashahrdami:fix/fetch-retry-request-body

Conversation

@pouyashahrdami

Copy link
Copy Markdown

Fixes #196

fetchWithRetry sends the same Request instance on every attempt, but the first attempt consumes the body stream — so every retry of a body-carrying request (POST/PUT/PATCH) fails with Body has already been used. This breaks retry for all execute tool API calls proxied through GlobalOutbound: after a 429 the loop sleeps through every backoff delay and returns the original 429 anyway, and after a network error it surfaces a misleading TypeError instead of retrying.

Fix: send a clone on every attempt that can still be retried; the final attempt consumes the original, so no cloned body is left unconsumed.

Tests: three new cases covering retry-after-429, retry-after-network-error, and final-attempt identity — all reproduce the failure on main (existing tests only used string URLs, which is why this was never caught). npm run check passes.

fetchWithRetry sent the same Request instance on every attempt, but the
first attempt consumes the body stream, so every retry of a POST/PUT with
a body failed with "Body has already been used". This broke retries for
all execute-tool API calls proxied through GlobalOutbound: a 429 slept
through the backoff delays and returned the original 429 anyway, and a
network error surfaced a misleading TypeError instead of retrying.

Send a clone on every attempt that can still be retried and let the final
attempt consume the original.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fetchWithRetry can't retry requests with a body (reuses a consumed Request)

1 participant