next.js: [NEXT-1181] DynamicServerError: Dynamic server usage: cookies
Verify canary release
- I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 22.4.0: Mon Mar 6 20:59:28 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T6000
Binaries:
Node: 16.13.2
npm: 9.3.0
Yarn: 1.22.19
pnpm: 7.25.1
Relevant packages:
next: 13.4.1
eslint-config-next: 13.3.0
react: 18.2.0
react-dom: 18.2.0
Which area(s) of Next.js are affected? (leave empty if unsure)
App directory (appDir: true)
Link to the code that reproduces this issue
https://github.com/focux/next-cookies-bug
To Reproduce
- Clone the repository
- Run
npm run build
Describe the Bug
After upgrading to Next from 13.3.5
to 13.4.1
, I’m getting a lot of errors that say:
- info Creating an optimized production build ..node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
DynamicServerError: Dynamic server usage: cookies
at staticGenerationBailout (/Users/[redacted]/Projects/[redacted]/apps/web-app/.next/server/chunks/3311.js:46379:21)
at cookies (/Users/[redacted]/Projects/[redacted]/apps/web-app/.next/server/chunks/6647.js:172:62)
at getAccessToken (/Users/[redacted]/Projects/[redacted]/apps/web-app/.next/server/chunks/9041.js:30473:40)
at /Users/[redacted]/Projects/[redacted]/apps/web-app/.next/server/chunks/9041.js:30505:55
at /Users/[redacted]/Projects/[redacted]/apps/web-app/.next/server/chunks/6647.js:2598:44 {
digest: 'DYNAMIC_SERVER_USAGE'
}
The app works good when running it on development mode.
Expected Behavior
According to the docs, using the cookies
function automatically opt-ins my pages to dynamic rendering.
So I would expect the build to succeed as before and also those errors to be clearer to at least know in what page is originating.
Which browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 39
- Comments: 67 (5 by maintainers)
Commits related to this issue
- Add force-dynamic https://github.com/vercel/next.js/issues/49373 — committed to dlwocks31/emobridge by dlwocks31 a year ago
- Add docs page for uncaught DynamicServerErrors (#53402) When using imports from `next/headers` in a layout or page, `StaticGenerationBailout` will throw an error to indicate Next.js should fallback... — committed to vercel/next.js by ztanner a year ago
I solved this problem simply by adding this line to the app/layout.tsx file
export const dynamic = 'force-dynamic'
The
export const dynamic = 'force-dynamic
line worked for me when placed in mylayout.tsx
file, but when I navigate to a different page using theuseRouter
hook, I get the following err:Error: Dynamic server usage: force-dynamic
Going from
to
fixed it for me.
Everywhere I was passing cookies on a server component was giving me this issue. It was mainly on the Supabase getSession() funciton that used createServerComponentClient() function. To fix, I added ‘use server’ to the getSession() function and was able to clear the issue.
Does anyone have an update on this issue? Is this expected behaviour of Next.js or something we can hope to change in the future?
Currently facing the same issue with Supabase when it consumes
cookies
fromnext/header
in a server component.Same problem here. Have an app with i18n setup where the root layout (
app/[lng]/layout.tsx
) has the following codeAny redirects to pages that either use
searchParams
or declare any of the dynamic route options causes the app to throw an error in development.Removing the code from the
layout.tsx
fixes the problem, but makes all of the routes server-side-generated, which is not what I want.Any suggestions on how to fix that?
Hey all, I had a look into the reproduction provided on the initial issue post. It seems the reason that it doesn’t work in the urql case is that it uses setTimeout / out of band promises quite a bit.
The reason you can call
cookies()
anywhere in React components / other functions called from React rendering is that we leverage Async Context. More precisely the implementation of the same concept that currently exists in Node.js which is called AsyncLocalStorage (don’t get confused, this has nothing to do with the browser localstorage api). The way that Async Context works is that you can pass values within the same call stack, if setTimeout or such is used it’ll break out of that call stack and the value can’t be read, causing an error that say something about the context missing.The case that you’re running into is different though, it seems the
authExchange
is not bound to.query
/.toPromise
, which then causes an Uncaught Exception on the promise. The reason you see this as an error is that we leverage throwing to opt-out of static rendering during a build. When you callcookies()
/headers()
(or other APIs that opt out of static rendering) an error is thrown (Dynamic server usage: cookies
), this error is caught by Next.js and will automatically mark the page as needing dynamic rendering. The problem here with urql is that because the function called is unbound a global rejection happens.Changing the code to something like this will work:
Codesandbox with the changes running the production build: https://k7q35k-3000.csb.app/ Code on codesandbox: https://codesandbox.io/p/github/focux/next-cookies-bug/csb-k7q35k/draft/peaceful-wescoff?file=/lib/urql.ts:21,27
However I think this is still a bug in urql as well so I’ll dig a bit deeper into that.
The reason that adding
force-dynamic
worked for most people in this thread is that you then skip rendering during the build altogether as it’s explicitly saying the page is dynamic.I’ll have a look into the Supabase case as well, seems like it’s potentially similar to the urql case where something is not bound to the same call stack.
We’ll also work on improving the error / guidance around why the error happens.
What would be super helpful is if you can provide a GitHub repository or Codesandbox when running into this. I’m expecting most people on this thread to be running into different issues that has the same outcome. I.e. I’ve seen cases where awaiting promises was forgotten and such that also cause this.
Running into the same issue,
export const dynamic = 'force-dynamic'
does “fix” the issue but it’s not an ideal solution I think. Also seems like https://github.com/vercel/next.js/issues/49066 and https://github.com/vercel/next.js/issues/50634 and are relatedI am getting this same error while trying to use Supabase auth using Cookies in Next
Here are my Supabase files for reference
middleware.js
route.js
page.js
The issue was solved through this way: https://github.com/vercel/next.js/issues/45371#issuecomment-1655408690
For statically pre-rendered pages I used, e.g.:
But this feels like a temporary solution. I don’t want to put “force-static” to every ISR page.
In my case, using the latest NextJS (13.4.9) and
@supabase/auth-helpers-nextjs@0.7.3
my issue was related to the using supabase server component client on page routes that were not dynamic (i.e. /home, /settings instead of /task/[taskId]).I thought including
import { cookies } from 'next/headers';
on apage.tsx
automagically opted into dynamic rendering it seems like during the next build process if the route isn’t dynamic it may be trying to render it statically. 🤷I was able to workaround it by finding the pages that used the the supabase server component client and added a force-dynamic.
In my case I wanted them to always be dynamic, so it worked well.
This helps with dev server on initial load, but any change to any file immediately shows this:
It throws an error on the page with
const dynamic = 'force-dynamic'
if the root layout usesgenerateStaticParams
.If I remove the
force-dynamic
directive and use onlysearchParams
on the same page, there’s no error thrown, but the searchParams object is empty. Only after a hard page refresh, thesearchParams
are updated with a correct value.I’m using 13.4.7 and a downgrade to 13.4.6 and 13.4.3 did not help.
The same happens for other “dynamic” opt-in functions like
searchParams
andheaders
. Maybe rename this issue to reflect as such?I have a similar issue Error: Dynamic server usage: cookies
When I removed
generateStaticParams
from the layout, it no longer occurs.But we need this during static page generation on the build, right?
to be fair, app router is not stable yet, I decided to try a new project on it and I regret already. It’s very early and hard to get help. My workaround in your case is to use the client component which work correctly instead. You will lose your SSR optimization but you can still retrieve your session on client side.
I solved it by adding
export const revalidate = 0;
to thelayout.tsx
Just had this issue today after upgrading my package.json. Can confirm that exporing “force-dynamic” makes the issue go away
This would mean that your whole page will be dynamic and not statically generated at run/build time which is the whole point of
generateStaticParams
as an example lets say you have a e-commerce product page. We want that whole page to be statically generated but only the price should be dynamic based on the currently logged in customer. I believe that this is currently not possible with Next.jsOkay progress: Turns out
export const dynamic = 'force-dynamic'
is exactly the correct current workaround on pages & layouts.My problem lies with that one server component (a navbar) that’s on every page. Since that force-dynamic line doesn’t work for components, it looks like I’ll be moving the db call to a client component within it and see if that helps
I’m facing the same issue, but none of the above solutions seem to be resolving it for me.
next@13.4.10
and@supabase/auth-helpers-nextjs@0.7.3
npm run build
fails withError: Call rentries were exceeded
after printing the following error 17 times:I have one server layout calling
createServerComponentClient<Database>({ cookies })
as well as two server-rendered pages and one server-rendered component. The layout is shared by three more pages, and the component is on every page.Every file that imports cookies from
next/headers
has been givenexport const dynamic = 'force-dynamic';
but without success.I’ll update if I figure this out, other suggestions welcome!
A nice solution to this might be to have these automatically set as default options for pages that consume dynamic functions like
cookies
.In case it helps someone, my problem with using cookies was about using generateStaticParams in layout.tsx. Using generateStaticParams prevents accessing cookies and headers since it generates paths at build time rather than runtime. Once I removed it, I was able to access cookies without any problem. Also note that revalidate and force-dynamic will be ignored if generateStaticParams defined.
Ideally though we would want to cache where we can and
force-dynamic
would prevent this, correct? Hopefully there will be a way to do this in future with caching!@emrecoban I added to all the pages I was experiencing the message.
@emrecoban I only needed to add it to one single page (as seen in my code above)
I do have the same specific error case with
next-intl
.As far as I’m aware, you can mix static and dynamic down to the layout level, ie, a layout could be static, with dynamically pages iirc. I may be wrong though.
You are correct as far as I understand either a page is static or dynamic. I used to think we can mix those components to get best of both worlds.
@tatwater As far as I remember with my failed builds, it didn’t tell me which page was erroring during build. Is this the same on your end as well?
If so, would be great if Next.js told us what page was failing during build for
DynamicServerError
errors.I was facing the same issue, but i eventually found out that the error only showed when the ‘dynamic’ page (in my case, because i am using the cookies) was rendered through the router (using the Link component from next-intl). When i simply replaced the Link with a normal “a” tag, the error message not longer shows.
My problem is solved by using this line in every API Route.js
export const dynamic = 'force-dynamic';
Ex.
In my case, the whole site is backend with Clerk-auth (which server method
currentUser()
uses cookies obviously) so every page (and the middleware) is doing that. Does theapp dir
setup not allow to setforce-dynamic
on the site level (innext.config.js
)?Also, as I understand it correctly, this is just a warning from Next.js build tools (like eg. when you are using experimental API’s). So I don’t really understand why this is throwing errors. In my case I don’t see the errors in build output as they are caught by Sentry.
I’m getting this error too, I managed to squelch the error but it still didn’t compile any api route pages 😦
So far I’ve tried - export const dynamic = ‘force-dynamic’ in both page and layout files and in api routes
I had a similar problem with
draftMode()
and as a quick workaround I just added a try catch block to make sure that I can access the cookies. With this I can still generate the pages withgenerateStaticParams
I think you could do the same only for cookies.
I just started with next.js. I know it doesn’t make sense to access cookies when the pages are getting pre-generated, but I also didnt’t figure out a better way to solve this.
Is that the correct way?