If there is an async onSend hook registered to the server, any data fetching request (i.e. /-/data/...) will lead to an ELIFECYCLE fatal error:
2025-09-14 01:03:51.975+0300 - info - GET /-/data/data-fetching-page - incoming request
2025-09-14 01:03:52.004+0300 - warn - Reply was already sent, did you forget to "return reply" in the "/-/data/data-fetching-page" (GET) route?
2025-09-14 01:03:52.004+0300 - info - request completed
node:_http_server:352
throw new ERR_HTTP_HEADERS_SENT('write');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot write headers after they are sent to the client
at ServerResponse.writeHead (node:_http_server:352:11)
at safeWriteHead (.../node_modules/.pnpm/[email protected]/node_modules/fastify/lib/reply.js:553:9)
at onSendEnd (.../node_modules/.pnpm/[email protected]/node_modules/fastify/lib/reply.js:618:5)
at wrapOnSendEnd (.../node_modules/.pnpm/[email protected]/node_modules/fastify/lib/reply.js:546:5)
at next (.../node_modules/.pnpm/[email protected]/node_modules/fastify/lib/hooks.js:292:7)
at handleResolve (.../node_modules/.pnpm/[email protected]/node_modules/fastify/lib/hooks.js:309:5) {
code: 'ERR_HTTP_HEADERS_SENT'
}
Node.js v22.18.0
ELIFECYCLE Command failed with exit code 1.
- Synchronous hooks do not lead to the error
preSerializationandonResponseasync hooks do not lead to the error
To ensure that this bug is not caused by my misconfiguration of an MRE, there are alternative steps to reproduce it from the official fastify-vite repo:
npx giget gh:fastify/fastify-vite/starters/react-typescript react-typescriptcd react-typescriptpnpm i- Add async hook to
src/server.ts:
server.addHook('onSend', async () => {
await Promise.resolve()
});pnpm dev- Send a data fetching request (e.g., go to
/using-datafromhttp://127.0.0.1:3000/)