Closed robinComa closed 7 months ago
Is there a workaround for this? Will this be fixed?
@fab1an @robinComa
Two things were causing this behavior on my project:
I was using an instant loading state (loading.tsx file on the same level as the page.tsx). I don't know the specifics, but it does make sense because the loading appears before anything else, so the server needs to send some status code.
I was implementing a client component that functioned as a wrapper on the whole layout, so any rendered page used it. It was a provider for i18n values, I didn't go deeper into how it interacted with everything else to cause the wrong status code to be sent, but just removing it works.
Anyway, hope this is relevant to someone.
@caiolrm Thank you for the tipp. I just removed the dynamic route and copy and pasted all files for every [id]
that I need to support.
@ijjk Sorry for involving you, but will this ever be fixed? This is a terrible, reproducible bug, that's been open for half a year.
Wrong status-codes served by a webserver should be a core concern.
The only way to workaround it is to not use dynamic routes. At that point I can go back to nginx/apache2.
Same here... Are we seriously not able to set 404 status codes? The docs for notFound
says:
/**
* When used in a React server component, this will set the status code to 404.
* When used in a custom app route it will just send a 404 status.
*/
export declare function notFound(): never;
But it clearly doesn't work.
@Enngage The issue is with the compbination of caching and dynamic routes.
If you route uses notFound()
AND contains an id like [id]
it will serve 404 on the first load, but 200 on the subsequent cached loads.
I suspect this is why it wasn't fixed yet. It is too complex to reproduce.
@Enngage The issue is with the compbination of caching and dynamic routes.
If you route uses
notFound()
AND contains an id like[id]
it will serve 404 on the first load, but 200 on the subsequent cached loads.I suspect this is why it wasn't fixed yet. It is too complex to reproduce.
Hey, it doesn't return 404 on first load... that's the problem because then google indexes the page. It's true we are using dynamic routes with url parameters.
We actually "solved" it by creating a "/404" route and redirected notFound
items to this route manually. The /404
route seems special
as it applies the 404 status code, but I haven't found it in docs. It was likely there in the old pages
router, but not with the new one. It's all bit odd.
@Enngage So you are using redirect to send 307 to the user, which then redirects to a 404 page. Are you sure this is not hurting SEO?
@Enngage So you are using redirect to send 307 to the user, which then redirects to a 404 page. Are you sure this is not hurting SEO?
We are redirecting from server straight to '/404' route which applies the 404. Its the only way we could achieve 404 response status code and stop google from indexing every single path even if it does not exist.
I wish the 'notFound' method worked as documented, but it doesn't.
Can you show us the function you use to do the redirect?
Can you show us the function you use to do the redirect?
We are using redirect
-> import { redirect } from 'next/navigation';
This bug seems like a huge pain. Maybe I'm missing something, but how are you supposed to use dynamic routes if they can't be 404'd?
Is this also fixed by #55542?
@caiolrm , thanks for the tip! I removed loading.tsx and it worked.
I have the same issue , i call notFound() but my doc of page is return 200 status code , how can change that to 404 ?????
Next js 14 is so popular i wonder how such an issue is still present on the framework logic.. please put this as high priority we need 404 status code after loading not found pages!
We were also experiencing this issue and as mentioned by @caiolrm, removing the use client
providers we had wrapping our component hierarchy fixed the issue.
Digging a little deeper we found the issue was actually being caused by useEffects
in the client providers that were making async calls.
Refactoring to remove these useEffects fixed the issue and the "not found" page now returns a status code of 404
.
This also incidentally fixed an issue we were experiencing with generateMetadata
not rendering the app if there was a delay when fetching dynamic meta data.
Also experiencing the same issue. Our structure looks like this and this will recreate the problem:
app -> [slug-route] -> homepage -> another-static-page -> another-static-page -> loading.js -> not-found.js
By removing the loading.js page the issue goes away and 404 is returned instead of 200 status for the not found page (for both client side and server side).
This is a serious issue as it forces you to choose between User Experience (loading page) and SEO (where 404s are critical for crawl budget and clarity) - two of the main reasons we chose Next JS. If anyone can look into/resolve this (e.g. @balazsorban44 ), we'd be very grateful.
@GXM245, as a compromise - you can use something like progress bar: https://www.npmjs.com/package/next13-progressbar?activeTab=code (or write something similar by yourself). You can see such solution on github too. So there is no loading.js, but there is still an effect of loading state when clicking internal links.
Thanks @MaciejWira! I'll take a closer look at that - and yes, you're right, the most suitable option at this point would be to write something ourselves. I wonder how many of us have similar setups but unaware that our pages are, in fact, returning a 200 when they should be a 404. I only discovered this myself after a SEO crawl where a load of pages I expected to be a 404 were returning a 200.
@timneutkens would you be able to lend us your ear on this one? This is quite fundamental to the response codes that core Next JS functionality returns.
So right now Nextjs starts streaming data immediately with loading.js and because how the web works it has to have a status code 200. Later on while processing the data we decide it should be a notfound (which is cool btw) and can't change the status code.
I suggest devs expose an experimental flag in NextConfig so that people can opt out of loading.js only if route is dynamic or even if it uses some special function that requires a change in status code (e.g. notfound, forbidden)
Like experimental.ignoreSuspenseForStatus Code
the same issue with redirect()
where it will have a status code of 200
instead of 307
. This is a pretty big issue SEO-wise
This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.
Verify canary release
Provide environment information
Which area(s) of Next.js are affected? (leave empty if unsure)
App directory (appDir: true), Routing (next/router, next/navigation, next/link)
Link to the code that reproduces this issue or a replay of the bug
https://codesandbox.io/p/sandbox/cranky-pine-f9s292?file=%2Fapp%2Fpage.tsx%3A1%2C1
To Reproduce
Describe the Bug
When notFound is called, the 404 page is correctly displayed, but the status is 200 :
Expected Behavior
The HTTP status code should be 404
Which browser are you using? (if relevant)
Chrome Version 114.0.5735.106 (Build officiel) (x86_64)
How are you deploying your application? (if relevant)
next start