Skip to content

Docs: Breaking changes in res.setHeader() timing behavior with handle(req, res) in custom servers (Next.js 13/14+) #82387

@quicksilversel

Description

@quicksilversel

What is the documentation issue?

Hi team! 👋
First off, thank you for the amazing work on Next.js! it’s been a joy to use and continually improves with each release.

While upgrading from Next.js 12 to 14 in a project that uses a custom Fastify server, I noticed a subtle behavior change that wasn’t obvious from the migration guide or release notes:

❌ No longer works in Next.js 14

// works in Next.js 12
serve.all('/*', async (req, reply) => {
  await handle(req.raw, reply.raw)

  reply.raw.setHeader('Set-Cookie', 'sessionId=abc123; Max-Age=2592000')

  reply.hijack()
})

✅ Works in Next.js 14

serve.all('/*', async (req, reply) => {
  reply.raw.setHeader('Set-Cookie', 'sessionId=abc123; Max-Age=2592000')

  await handle(req.raw, reply.raw)

  reply.hijack()
})

After some digging, I realized that handle() now likely begins streaming the response immediately, which means the headers must be set beforehand. This makes sense from an implementation perspective, but it might catch developers like us off guard, especially if they’re migrating custom server setups from v12.

Would it be possible to add a note about this to the Next.js 14 release notes or custom server documentation? Even a short warning that res.setHeader() must come before handle() would go a long way for those using Fastify or Express with Next.js.

Thank you again for your hard work and time 🙏

Is there any context that might help us understand?

Environment

  • Next.js: 14.2.14
  • Server: Fastify 4.11.0 (custom server)
  • Runtime: Node 20.18.0
  • Reproducible: Yes, with minimal custom server setup

Does the docs page already exist? Please link to it.

https://nextjs.org/blog/next-14

Metadata

Metadata

Assignees

Labels

ImprovementReport possible improvements to make in our documentation

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions