Skip to main content
GoodFirstPicks
DashboardIssuesReposLeaderboard

GoodFirstPicks by Leaveitblank © 2026

CreatorRequest a RepoPrivacy PolicyTerms of Service
Incorrect HTTP error status codes from non-streaming generateMetadata | GoodFirstPicks

Incorrect HTTP error status codes from non-streaming generateMetadata

vercel/next.js 10 comments 26d ago
View on GitHub
mediumopenScope: somewhat clearSkill match: maybeNext.jsTypeScriptReact

Why this is a good first issue

HTTP status codes are incorrect when streaming is blocked and layout.js is present.

AI Summary

The issue involves incorrect HTTP status codes (200 instead of 404 or 307) when `generateMetadata()` blocks streaming and a `layout.js` file is present. The expected behavior is to return the correct status codes before streaming starts. The problem requires understanding Next.js's streaming and metadata handling.

Issue Description

Link to the code that reproduces this issue

https://github.com/p00000001/error-status-codes-bug

To Reproduce

  1. Start the application
  2. Click the Throw notFound() page link and monitor the http status response in DevTools
  3. Click the Throw redirect() page link and monitor the http status response in DevTools

Current vs. Expected behavior

  • In Next.js 15, generateMetadata() became async to support metadata streaming by default: https://nextjs.org/docs/app/api-reference/functions/generate-metadata#streaming-metadata
  • When streaming, I understand it is not possible to change the HTTP response code as the response headers have already been sent. Therefore, by default calling notFound() and redirect() from generateMetadata() will return a 200 response code and use client-side JavaScript to handle functionality.
  • next.config.js permits a property htmlLimitedBots to block streaming until generateMetadata() is resolved.
  • When streaming is blocked for a user agent, calling notFound() or redirect() from generateMetadata() should return a 404 and 307 status code respectively as streaming has not started.
  • This works as expected when there is no layout.js in the root directory. However, when there is a layout.js file present, the status code is always 200 - the same behaviour as when streaming is active.
  • When generateMetadata() is blocking streaming, I would have expected the same status code behaviour regardless of the presence of layout.js, as the desired status code is already known before streaming has started?
  • I appreciate some crawlers can make “soft” interpretations of embedded not found page content and redirect meta tags, but this is not as reliable as http status codes, and even for crawlers that can, it could use up extra “crawl budget” processing the page.
  • To test this, I have created a sample app, and changed the config to: htmlLimitedBots: /.+/ so that all user agents get blocked generateMetadata().

GitHub Labels

Error Handling

Want to work on this?

Claim this issue to let others know you're working on it. You'll earn 20 points when you complete it!

Risk Flags

  • streaming behavior
  • HTTP status codes
  • layout.js interaction
Loading labels...

Details

Points20 pts
Difficultymedium
Scopesomewhat clear
Skill Matchmaybe
Test Focusedno