Skip to content

fix(fetch): clone request on retry to support requests with body - #79

Open
lucasros98 wants to merge 1 commit into
vippsas:mainfrom
lucasros98:fix/clone-request-on-retry
Open

fix(fetch): clone request on retry to support requests with body#79
lucasros98 wants to merge 1 commit into
vippsas:mainfrom
lucasros98:fix/clone-request-on-retry

Conversation

@lucasros98

@lucasros98 lucasros98 commented May 10, 2026

Copy link
Copy Markdown

Summary

Closes #78.

fetchRetry was passing the same Request object to fetchJSON on every retry attempt. Once a Request body has been consumed by a fetch call, the same Request object cannot be used again — the runtime throws:

TypeError: Cannot construct a Request with a Request object that has already been used.

This affected any POST/PUT request with a body when the first attempt returned a retryable status (5xx). GET requests without a body were unaffected, which is why the existing retry tests did not catch it.

Fix

Call `request.clone()` before each fetch attempt so the original `Request` remains unconsumed and the next retry can construct a fresh fetch from it.

-    const result = await fetchJSON<TOk, TErr>(request);
+    const result = await fetchJSON<TOk, TErr>(request.clone());

Test plan

Added a regression test (`fetchRetry - should retry POST request with body without consuming it`) that:

  1. Mocks a POST endpoint that returns 500 on the first attempt and 200 on the second
  2. Sends a `Request` with `method: POST` and a JSON body
  3. Asserts that the retry succeeds

This test fails on `main` with the exact stack trace from #78:

at fetch (https://jsr.io/@hongminhee/deno-mock-fetch/0.3.2/mod.ts:56:17)
at fetchJSON (src/fetch.ts:63:26)
at attemptFetch (src/fetch.ts:33:26)
at attemptFetch (src/fetch.ts:46:12)

…and passes with this change. All existing tests continue to pass (89 total).

  • `deno test` — 89 passed
  • `deno lint` — clean
  • `deno fmt --check` — clean

Closes vippsas#78.

The fetchRetry function was passing the same Request object to fetchJSON
on every retry attempt. Once a Request body has been consumed by a fetch
call, the same Request object cannot be used again — the runtime throws
'TypeError: Cannot construct a Request with a Request object that has
already been used'.

This affected any POST/PUT request with a body when the first attempt
returned a retryable status (5xx). GET requests without a body were
unaffected, which is why the existing retry tests did not catch it.

Fix: call request.clone() before each fetch attempt so the original
Request remains uncon­sumed and the next retry can construct a fresh
fetch from it.

Added a regression test that performs a POST with a JSON body, fails
once with 500, and then succeeds on retry. The test fails on master
with the exact stack trace from vippsas#78 and passes with this change.
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.

TypeError: Cannot construct a Request with a Request object that has already been used in fetchJSON

1 participant