getting write after end error when using async preserialization hook
ritikrao1 opened this issue · comments
Prerequisites
- I have written a descriptive issue title
- I have searched existing issues to ensure the bug has not already been reported
Fastify version
4.26.2
Plugin version
No response
Node.js version
14.18.0
Operating system
macOS
Operating system version (i.e. 20.04, 11.3, 10)
14.3
Description
i have a simple server, and in it i have a preserialization with async handler which modifies the payload and return the newpayload, when this newpayload is returned and preserialization hook ends and onsend hook ends i get the error
Error [ERR_STREAM_WRITE_AFTER_END]: write after end at new NodeError (internal/errors.js:322:7) at writeAfterEnd (_http_outgoing.js:694:15) at write_ (_http_outgoing.js:706:5) at ServerResponse.write (_http_outgoing.js:687:15) at onSendEnd (/Users/rrao.int/Desktop/scripts/node_modules/fastify/lib/reply.js:690:7) at onSendHook (/Users/rrao.int/Desktop/scripts/node_modules/fastify/lib/reply.js:557:5) at preSerializationHookEnd (/Users/rrao.int/Desktop/scripts/node_modules/fastify/lib/reply.js:540:3) at next (/Users/rrao.int/Desktop/scripts/node_modules/fastify/lib/hooks.js:289:7) at handleResolve (/Users/rrao.int/Desktop/scripts/node_modules/fastify/lib/hooks.js:306:5) at processTicksAndRejections (internal/process/task_queues.js:95:5) Emitted 'error' event on ServerResponse instance at: at writeAfterEndNT (_http_outgoing.js:753:7) at processTicksAndRejections (internal/process/task_queues.js:83:21) { code: 'ERR_STREAM_WRITE_AFTER_END' }
looking at the stack trace it seems that onSend hook is completed and when it tries to send the payload it throws this error and stops nodejs execution
Steps to Reproduce
const fastify = require("fastify");
const app = fastify({logger: true});
app.addHook('preHandler', async (req, res) => {
console.log("authentication");
return ;
})
app.get('/', {handler: async (req, res) => {
req.result = { msg: "hello"};
res.status(200).send(req.result);
}})
const asyncfunction = async ( ) => {
console.log('in async function');
return {};
}
app.addHook('preSerialization', async (req, res, payload) => {
// Assuming asyncfunction returns a promise
const newPayload= await asyncfunction();
return newPayload;
})
app.addHook('onReady', (done) => {
console.log("Service running on port: 3000");
done();
});
app.listen({host: 'localhost', port: 3000});
this is the only file and run the server and hit the api "/" you will get the error.
Expected Behavior
expected the api to run without a error get the newPayload changed in preserialization hook
👋
When using a combination of an async/await
function with the call to reply.send
; you need to explicitly return the reply
instance to allow fastify
to control the flow properly.
Otherwise is highly possible the response was sent when the promise was resolved, leading to this problem.
i.e. instead of
app.get('/', {handler: async (req, res) => {
req.result = { msg: "hello"};
res.status(200).send(req.result);
}})
do this:
app.get('/', {handler: async (req, res) => {
req.result = { msg: "hello"};
res.status(200).send(req.result);
return res;
}})