fastify / fastify

Fast and low overhead web framework, for Node.js

Home Page:https://www.fastify.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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;
}})