Environment
- Node.js: v24.14.0 (undici 7.21.0)
- Platform: macOS 26.4 (Apple Silicon)
Description
In undici 7.x, creating a Request with a ReadableStream body causes an assertion failure:
Error: expected non-null body source
This is a breaking change from undici 6.x (Node 22 and earlier) where this worked fine.
Reproduction
const body = new TextEncoder().encode(JSON.stringify({ test: true }));
// Create original Request with Uint8Array body
const originalReq = new Request('https://example.com', {
method: 'POST',
body,
headers: { 'Content-Type': 'application/json' }
});
// Read the body as ReadableStream
const bodyStream = originalReq.body;
// Create new Request from ReadableStream (common pattern in middleware/proxies)
const newReq = new Request(originalReq.url, {
method: originalReq.method,
headers: originalReq.headers,
body: bodyStream,
duplex: 'half',
});
// Try to fetch with the new request
await fetch(newReq);
// → Error: expected non-null body source
Root Cause
In undici/lib/web/fetch/index.js, there's an assertion:
if (request.body != null) {
assert(request.body.source != null)
request.body = safelyExtractBody(request.body.source)[0]
}
When a Request is created with a ReadableStream body (instead of Uint8Array, string, etc.), the body.source property is null, causing the assertion to fail.
Impact
This breaks legitimate use cases:
- Middleware that re-creates requests (e.g., Next.js's fetch patching, proxies)
- Libraries that create intermediate
Request objects (e.g., @atproto-labs/fetch-node for SSRF protection)
Expected Behavior
Creating a Request with a ReadableStream body should work, as it did in undici 6.x (Node 22).
Workaround
Downgrade to Node.js 22 (undici 6.x) or pre-read the body as ArrayBuffer before creating the new Request.
Question
Is this strict assertion intentional? If so, what's the recommended pattern for middleware that needs to re-create Request objects?
Environment
Description
In undici 7.x, creating a
Requestwith aReadableStreambody causes an assertion failure:This is a breaking change from undici 6.x (Node 22 and earlier) where this worked fine.
Reproduction
Root Cause
In
undici/lib/web/fetch/index.js, there's an assertion:When a
Requestis created with aReadableStreambody (instead ofUint8Array,string, etc.), thebody.sourceproperty isnull, causing the assertion to fail.Impact
This breaks legitimate use cases:
Requestobjects (e.g.,@atproto-labs/fetch-nodefor SSRF protection)Expected Behavior
Creating a
Requestwith aReadableStreambody should work, as it did in undici 6.x (Node 22).Workaround
Downgrade to Node.js 22 (undici 6.x) or pre-read the body as
ArrayBufferbefore creating the newRequest.Question
Is this strict assertion intentional? If so, what's the recommended pattern for middleware that needs to re-create
Requestobjects?