Support custom HTTP Status Code
for Server Components
#53225
-
Previous Proposal
GoalsManage custom Handling
|
Beta Was this translation helpful? Give feedback.
Replies: 38 comments 53 replies
-
@devjiwonchoi |
Beta Was this translation helpful? Give feedback.
-
While I understand the request. It seems there is a misunderstanding about when streaming starts and how that relates to the status code and your code. This proposal can't work because of limitations with streaming, specifically you can't set the status code after the headers have been sent and the stream has started. At the point where the TLDR: because of streaming rendering and the preinitialization (preamble part of the request) in React you can't modify the status / headers, that's also why you can't set cookies / set headers during server components rendering. |
Beta Was this translation helpful? Give feedback.
-
Hi! Thanks for giving this a go! I created the #50383 discussion. The The Server components could also be nested. A fetch call could be triggered in a RSC further down (also consider working with multiple fetch in different server components), then it gets hard to solve how to use the I think it feels more logical to have a |
Beta Was this translation helpful? Give feedback.
-
"Next.js will also return a 404 HTTP status code." Next returns HTTP 404 only when it is raised from root |
Beta Was this translation helpful? Give feedback.
-
Hi there, any updates of this issue? |
Beta Was this translation helpful? Give feedback.
-
404 is just the one example of the codes what can be used to report the NOT FOUND error to the googlebot. For example, what if I need the 410 GONE code? With the next.js sounds impossible at the moment... (And yes, we use it in production, is not just my imagination) What if the user params are wrong, instead of sort=price he passed sort=test and I would like to send the status code 400 for this or even 403, so hacker knows I see his actions |
Beta Was this translation helpful? Give feedback.
This comment was marked as spam.
This comment was marked as spam.
-
We are facing the same issue. We use NextJS in production and are relying on status codes in our (Akamai) CDN to determine what responses can be cached and when to resort to failover. (see https://techdocs.akamai.com/property-mgr/docs/cache-http-err-responses and https://techdocs.akamai.com/property-mgr/docs/site-failover) |
Beta Was this translation helpful? Give feedback.
-
When is |
Beta Was this translation helpful? Give feedback.
-
Hey everyone, I've been thinking about this and to work along with stream, prefetch and set status before streaming like I've updated the proposal, check it out and please share your thoughts. |
Beta Was this translation helpful? Give feedback.
-
Hi, Are any updates and/or input required? Both from development, server, and SEO perspective it's a major requirement. |
Beta Was this translation helpful? Give feedback.
-
Would be great to see something moving forward in this regard, even if it's a plugin that needs to be installed separately. |
Beta Was this translation helpful? Give feedback.
-
I'm missing something or really there is no way to get (using "app dir") the http status code in the "error.js" client-side component page? Currently, I'm stuck on this, which I used to think that should be something simple in any framework/server (at least it is something very trivial in other stacks). My scenario: I have some roles and a check for users that could access a page or not. Sometimes, if the user access a page that does not have permission, I need to throw an error (passing the "403" as a property, for instance) that changes the "error.js" interface to show the specific situation (that is a "Forbidden" page and not a "Server error"). Any thoughts? |
Beta Was this translation helpful? Give feedback.
-
For anyone who's looking for potential solutions our approach could be valuable. So we have a need to respond with 410 status codes when user-generated content was removed from the website or has expired due to inactivity/unpaid accounts. What worked for us is to set the status code via next middleware by making an additional HEAD request to the API and then leveraging CDN (Fastly in our case, but I'm sure there should be similar functionality on others) Not ideal due to second request, but HEAD is lighter and you can optimize with caching per your need. A viable workaround but I'd love this type of thing to be available in a framework that's advertising to be the best SSR solution out there, or at least be way more explicit about this type of breaking/missing features. Middleware code: export async function middleware(request: NextRequest) {
const response = NextResponse.next();
const pathname = request.nextUrl.pathname;
if (*additional filtering based on pathname*) {
try {
const apiResponse = await fetch(`*api-route*`, { method: 'HEAD' });
response.headers.set('X-Status-Code', String(apiResponse.status));
} catch (error) {
logger.error(error);
}
}
return response;
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}; Fastly config (custom VCL snippet of type "deliver")
|
Beta Was this translation helpful? Give feedback.
-
We definitely need to be able sent a custom status code. It really matters when our Next.js projects need to have a good SEO implementations and deal with the search engine bots properly. |
Beta Was this translation helpful? Give feedback.
-
We really need this feature... |
Beta Was this translation helpful? Give feedback.
-
Any updates on this issue? We need to a way to send different status codes since we want to handle different error pages for unauthorized, server render errors, or BE errors. Can't even pass it through an error object since it will be hidden on production |
Beta Was this translation helpful? Give feedback.
-
Currently, the app router doesn’t allow sending 404 response codes for non-existent dynamic pages, which is essential for customer-facing websites. Adding this feature would significantly improve handling of these scenarios. Can we have this feature soon? |
Beta Was this translation helpful? Give feedback.
-
After spending tons of hours figuring out ways to have correct http status code for 404 and redirects, I tried to find what is actually enabling this Stream rendering for server side. I suggest you also trying to remove / move some stuff away from those Layout files - In our case for locales we used this - https://next-international.vercel.app/docs |
Beta Was this translation helpful? Give feedback.
-
@timneutkens any news? |
Beta Was this translation helpful? Give feedback.
-
I our use case, we need custom dynamic 404 page. Currently, The only workaround is to use client component and refetch data again at client so we can know the 404 reason, which is not optimal. If I can manually set status code at page level, then I can render custom not found page directly in the original page and achieve this. |
Beta Was this translation helpful? Give feedback.
-
To back up on the above and to add a few more uses cases:
|
Beta Was this translation helpful? Give feedback.
-
Do we have any actual solution of this problem? |
Beta Was this translation helpful? Give feedback.
-
As your docs says:
I understand the technical ground of this. But if I am correct, the response headers are sent to the client before page server component code executes only in case when there is a Let's me illustrate my considerations with the code. export default async function Article({ params }: { params: Params }) {
const { id } = await params;
await sleep(3000); // imitates fetching of article data
if (id === '206') {
return notFound(); // returns 404 HTTP status code
}
if (id === '207') {
return permanentRedirect('/article/208'); // returns 308 HTTP status code
}
if (id === '215') {
throw new Error('failed to fetch article with id 215'); // returns 500 HTTP status code
}
return (
<div className={styles.root}>
<h2>This is the article title for article with id: {id}</h2>
<div>Article content...</div>
</div>
);
} As I said I don't have any So my question is: why can't I set headers in page server component when there is no |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Sad to see even something basic like this isn't possible. I ended up creating a custom Apache module |
Beta Was this translation helpful? Give feedback.
-
Honestly, it boggles my mind that next.js can't support a feature that practically every other web framework of the last 20 years has had. |
Beta Was this translation helpful? Give feedback.
-
I don't think this should be marked as answered. My team has been using the App Router in production for over a year and a half and this remains one of the most frustrating limitations in the framework. It’s a real pain point that still hasn’t been addressed. I understand that on Vercel, the frontend and CDN layers are tightly integrated, but for self-hosted deployments, this creates major issues. When a page needs to return a specific HTTP status like 503, there's no reliable way to do so using the App Router. This isn't just an edge case. CDNs and reverse proxies depend on response headers, not HTML content, to make caching decisions. Without the ability to set proper status codes and headers we are flying blind. At the very least, there should be a way to disable the streaming response behavior so we can manage response headers in a normal Response object, or some supported API to let us set status codes from within a page or layout. This is a massive architectural gap that is being overlooked especially for teams running Next.js in a self hosted enviornment. |
Beta Was this translation helpful? Give feedback.
-
Agreed. I shelved a major project I'd started in next.js entirely for this reason and went looking for alternative mobile-first frameworks, eventually landing on [Expo](https://expo.dev/).
…________________________________
From: Patrick Piwowarczyk ***@***.***>
Sent: 10 June 2025 23:53
To: vercel/next.js ***@***.***>
Cc: ALB.Leach ***@***.***>; Comment ***@***.***>
Subject: Re: [vercel/next.js] Support custom `HTTP Status Code` for Server Components (Discussion #53225)
How is this marked as answered?
My team has been using the App Router in production for over a year and a half and this remains one of the most frustrating limitations in the framework. It’s a real pain point that still hasn’t been addressed.
I understand that on Vercel, the frontend and CDN layers are tightly coupled and abstracted, but for self-hosted deployments, this creates major issues. When a page needs to return a specific HTTP status like 503, there's no reliable way to do so using the App Router. This isn't just an edge case, CDNs and reverse proxies depend on response headers, not HTML content, to make caching decisions. Without the ability to set proper status codes and headers from a server-rendered page, we are flying blind.
At the very least, there should be a way to disable the streaming response behavior so we can manage response headers in a normal Response object, or some supported API to let us set status codes from within a page or layout.
This is a massive architectural gap that is being overlooked — especially for teams running Next.js in custom, non-Vercel environments.
—
Reply to this email directly, view it on GitHub<#53225 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AAC3ZLKQJINW3TQX2TIYYKD3C4ZTDAVCNFSM6AAAAAA2ZBJMDOVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTGNBSGUZDSNI>.
You are receiving this because you commented.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
While I understand the request. It seems there is a misunderstanding about when streaming starts and how that relates to the status code and your code. This proposal can't work because of limitations with streaming, specifically you can't set the status code after the headers have been sent and the stream has started.
At the point where the
Profile
component in the example runs the headers have already been sent and the stream has been started. This means that you can't change the status code / headers at that point. What we do fornotFound()
/redirect()
when they are called when the stream has started is adding meta tags recommended by Google for these cases.TLDR: because of streaming …