workerd TypeError: Response body already used in middleware chain
Fixes the single-use response body error in Workers middleware chains. This skill shows how to clone a response before the first read or read once and share the parsed value, so logging middleware no longer breaks the downstream handler. Use it when a middleware that reads the body causes 'body already used' errors further down the chain.
Fix Response body already used in middleware chain
TL;DR
Read each response body exactly once. Call response.clone() before the first read when two consumers need the body, or read once and pass the parsed value to both. The root cause is simple: response bodies are single-use streams in workerd, so the second read always throws.
Verbatim error
workerd TypeError: Response body already used in middleware chainSteps
- Find the two reads: search for
.json(),.text(), or.arrayBuffer()called on the same response variable in the middleware and the handler. Expected: you identify both read sites. - In the middleware that reads first, clone before reading:
const copy = res.clone();then readcopyfor logging and pass the originalresonward. Expected: the clone call happens before any consumption. - Alternative when both consumers live in your code: read once into a const and hand the parsed value to both consumers. Expected: a single read, no clone needed.
- If the reader is third-party middleware you cannot edit, wrap it: clone the response before it runs and restore from the clone after. Expected: downstream reads work.
- Verify with a quick test: read twice from the same variable without a clone to confirm the error, then apply the fix and confirm both reads succeed. Expected: no "body already used" error.
Use this when
- "Response body already used" appears in a workerd middleware chain
- A logging or metrics middleware that reads the body breaks the downstream handler
- Two plugins each try to parse the same fetch response
Not for this skill when
- The error is about a request body already used (same shape on Request, mirror fix)
- TransformStream writer errors appear instead
- The body is consumed across a redirect (redirect handling, not double-read)
Variant phrasings
- "body used already" response already read
- TypeError body stream locked workers
- cannot read response body twice cloudflare workers
- Response body has already been consumed
Why it happens
Response bodies are ReadableStreams: reading locks and drains the stream. clone() tees the underlying stream so two readers can consume independently, but it must happen before the first byte is read. Middleware chains hit this constantly because each layer assumes it is the only reader.
Edge cases
clone()after a partial read throws, so clone eagerly at the top of the middleware.- Cloning a large body doubles memory use; when both consumers are yours, prefer read-once-and-share.
- 204 and HEAD responses have no body, so body guards around them are unnecessary.
Provenance
Resolved from the public thread: https://vectle.com/posts/pstfC2jekcsqDB2Bl-gDTzPw
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.