Prerequisites
Fastify version
5.2.0
Plugin version
No response
Node.js version
18.19.1
Operating system
Linux
Operating system version (i.e. 20.04, 11.3, 10)
Ubuntu 24.04.1
Description
With #5286, request handlers in Fastify can return JavaScript Responses, whose response bodies are backed by ReadableStreams. If the same response is sent multiple times instead of a fresh one for each request, it's possible for Fastify to crash when converting the ReadableStream underlying the response into a Readable. This is done here:
|
const nodeStream = Readable.fromWeb(payload) |
One can reproduce this error by running the following server and issuing a GET request to /:
const fastify = require('fastify');
const app = fastify({
logger: true,
});
const stream = new ReadableStream();
const response = new Response(stream);
stream.getReader();
app.get('/', (request, reply) => {
reply.send(response);
});
app.addHook('onSend', async () => {});
app.listen({
port: 8000,
});
{"level":30,"time":1735846078242,"pid":130836,"hostname":"???","msg":"Server listening at http://127.0.0.1:8000"}
{"level":30,"time":1735846082740,"pid":130836,"hostname":"???","reqId":"req-1","req":{"method":"GET","url":"/locked","host":"localhost:8000","remoteAddress":"127.0.0.1","remotePort":43396},"msg":"incoming request"}
onSend has been triggered.
node:internal/errors:496
ErrorCaptureStackTrace(err);
^
TypeError [ERR_INVALID_STATE]: Invalid state: ReadableStream is locked
at new NodeError (node:internal/errors:405:5)
at setupReadableStreamDefaultReader (node:internal/webstreams/readablestream:2153:11)
at new ReadableStreamDefaultReader (node:internal/webstreams/readablestream:829:5)
at ReadableStream.getReader (node:internal/webstreams/readablestream:350:14)
at Object.newStreamReadableFromReadableStream (node:internal/webstreams/adapters:500:33)
at Readable.fromWeb (node:internal/streams/readable:1444:27)
at sendWebStream (/home/jpeterson/Downloads/fastify-test/node_modules/fastify/lib/reply.js:673:31)
at onSendEnd (/home/jpeterson/Downloads/fastify-test/node_modules/fastify/lib/reply.js:636:5)
at wrapOnSendEnd (/home/jpeterson/Downloads/fastify-test/node_modules/fastify/lib/reply.js:536:5)
at next (/home/jpeterson/Downloads/fastify-test/node_modules/fastify/lib/hooks.js:292:7) {
code: 'ERR_INVALID_STATE'
}
Node.js v18.19.1
I think a good fix would be to wrap the Readable.fromWeb call in a try/catch block, but there may be a better place higher up in the call stack to wrap to prevent other errors from crashing the server.
Link to code that reproduces the bug
No response
Expected Behavior
No response
Prerequisites
Fastify version
5.2.0
Plugin version
No response
Node.js version
18.19.1
Operating system
Linux
Operating system version (i.e. 20.04, 11.3, 10)
Ubuntu 24.04.1
Description
With #5286, request handlers in Fastify can return JavaScript Responses, whose response bodies are backed by ReadableStreams. If the same response is sent multiple times instead of a fresh one for each request, it's possible for Fastify to crash when converting the
ReadableStreamunderlying the response into aReadable. This is done here:fastify/lib/reply.js
Line 673 in c5f4a17
One can reproduce this error by running the following server and issuing a GET request to
/:I think a good fix would be to wrap the
Readable.fromWebcall in atry/catchblock, but there may be a better place higher up in the call stack to wrap to prevent other errors from crashing the server.Link to code that reproduces the bug
No response
Expected Behavior
No response