payload
payload copied to clipboard
Cannot build with dynamicIO enabled.
Describe the Bug
When enabling the experimental dynamicIO feature, the following error occurs during build:
Error occurred prerendering page "/admin/[[...segments]]". Read more: https://nextjs.org/docs/messages/prerender-error
Error: Route "/admin/[[...segments]]" has a `generateMetadata` that depends on Request data (`cookies()`, etc...) or external data (`fetch(...)`, etc...) but the rest of the route was static or only used cached data (`"use cache"`). If you expected this route to be prerenderable update your `generateMetadata` to not use Request data and only use cached external data. Otherwise, add `await connection()` somewhere within this route to indicate explicitly it should not be prerendered.
Export encountered an error on /(payload)/admin/[[...segments]]/page: /admin/[[...segments]], exiting the build.
While this is experimental, the documentation for the new 'use cache' directive states that it aims to replace the unstable_cache API.
Given that we will be using the payload client directly in Server Actions, we will need a way to cache those actions with tags (for revalidateTag). React's cache doesn't support tagging for manual revalidation, which leaves only Next's unstable_cache and 'use cache' with cacheTag as options.
Link to the code that reproduces this issue
blank
Reproduction Steps
Enable experimental dynamicIO feature.
Build.
Which area(s) are affected? (Select all that apply)
area: core
Environment Info
Payload: beta-119 Node: 20 Next.js: 15.0.2-canary.9
Oh man thanks for the report here. This is a real can of worms. You're right, Next.js throws an error here but I am not sure why.
Reading the error, it basically says that generateMetadata depends on request data, but the rest of the page does not.
However, this is 100% untrue as our Page component definitely uses headers() which would opt the whole route into not being able to be prerendered.
I think this might be a Next.js canary thing...
I also just updated our /admin/[[...segments]] page template as the error message instructed, by adding await connection() but this did not fix the build error.
// import { connection } from 'next/server'
const Page = async ({ params, searchParams }: Args) => {
await connection()
return RootPage({ config, params, searchParams, importMap })
}
Gonna have to look into this one a bit further and get back to you!
got the same error and the await connection() doesn't help
import React, { FC } from 'react'
import { Metadata } from 'next'
import { connection } from 'next/server'
type DashboardProps = {
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export const generateMetadata = async (
props: DashboardProps
): Promise<Metadata> => {
const searchParams = await props.searchParams
const { page: currentPage } = searchParams
return {
description: `${currentPage}`,
}
}
const Page: FC<DashboardProps> = async () => {
await connection()
return <div>Page</div>
}
export default Page
and the log:
Next.js 15.0.2-canary.11
- Environments: .env.local, .env
- Experiments (use with caution):
· turbo
· dynamicIO
Creating an optimized production build ...
✓ Compiled successfully
✓ Linting and checking validity of types
✓ Collecting page data
Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
Error: Route "/" has a `generateMetadata` that depends on Request data (`cookies()`, etc...) or external data (`fetch(...)`, etc...) but the rest of the route was static or only used cached data (`"use cache"`). If you expected this route to be prerenderable update your `generateMetadata` to not use Request data and only use cached external data. Otherwise, add `await connection()` somewhere within this route to indicate explicitly it should not be prerendered.
Export encountered an error on /(public)/page: /, exiting the build.
⨯ Static worker exited with code: 1 and signal: null
node -v v22.11.0
Instead of using await connection() at the page level, wrapping the layout with <Suspense> solved the problem for me.
app/(payload)/layout.tsx
import configPromise from "@payload-config";
import "@payloadcms/next/css";
import { RootLayout } from "@payloadcms/next/layouts";
import React, { Suspense } from "react";
import "./custom.scss";
import { importMap } from "./admin/importMap";
type Args = {
children: React.ReactNode;
};
const Layout = ({ children }: Args) => (
<Suspense>
<RootLayout importMap={importMap} config={configPromise}>
{children}
</RootLayout>
</Suspense>
);
export default Layout;
See also the Next.js blog entry: Our Journey with Caching - Dynamic
I can't judge whether that's technically correct. My understanding of Next.js isn't deep enough for that.
I think wrapping the layout this high up would have a negative impact on the /api routes as well, but I'm not certain about that. I did also try wrapping the app/(payload)/admin/[[segments]]/page.tsx RootPage with Suspense, as well as creating a loading.tsx file (also generates a Suspense boundary), and finally creating a app/(payload)/admin/layout.tsx wrapping the children prop with Suspense. None of those worked.
It is interesting though that wrapping the root payload layout with Suspense works. This seems to indicate there's something in RootLayout causing the issue rather than RootPage as the error suggests.
This error said:
throw new CanaryOnlyError('experimental.dynamicIO');
^
CanaryOnlyError: The experimental feature "experimental.dynamicIO" can only be enabled when using the latest canary version of Next.js.
just upgrade npm i next@canary
@pedroaparecido As listed originally in my issue post, canary is being used. When you install canary, and enable dynamicIO, this issue occurs. While this is a canary-only option now, it has been stated by the Next.JS team to be the expected successor to the unstable_cache function. This would make the new use cache directive the only first-party way to cache server actions that use the local payload API with the ability to tag each cache and manually invalidate them.
Just bumped into this issue as well trying to deploy to Vercel.
@Figumari solution worked but I am getting the exact same error on my dynamic routes now too, outside of admin/.
Just bumped into this issue as well trying to deploy to Vercel. @Figumari solution worked but I am getting the exact same error on my dynamic routes now too, outside of
admin/.
Ditto.
There is no other way.
I'm getting this error right now after using "dynamicIO" experimental config, there is any news about it @jmikrut?
NextJS canary.33 have new experimental.useCache flag. Give it a try, guys. I think it'll help to fix issue for production build.
this is still an issue for me. any plans for payload to support ppr and dynamicIO within nextjs @jmikrut ?
Same issue for me. i moved over to next canary as i was sick of waiting for the new use cache, cachelife and cachetag functionality to come out. all of that works really well and seems stable so i expect it to be released to the main next release soon.
however, with the new use cache functionality, any use of headers(), cookies(), params, searchParams etc need to be inside a suspense boundary or it throws an error. ive sorted all the non payload side of my site and all works as expected, but im stuck as to how i can sort the payload admin side
is this being looked at yet. The use cache, cachelife and cachetag new features is the best thing next has added for a long time and really helps making caching a lot easier, so being able to use it with payload will be a big big help
Still an issue as of writing this.
@jmikrut are there any plans of making PayloadCMS 3.0 compatible with dynamicIO before the official Next.js release that adopts it? use cache and dynamicIO make caching much easier and would really stack up with the existing PayloadCMS DX. Current Next.js docs also heavily imply that it will soon replace the old caching system.
use cache actually works great out of the box. This is just to support the payload admin server components. It was working previously wrapping the root in a Suspense and making the whole thing dynamic, but that has broke recently.
Would be great to get the server components rocking.
use cache is going to be incredible with payload.
From: Aleksa Simovic @.> Sent: Thursday, June 5, 2025 7:08:55 AM To: payloadcms/payload @.> Cc: Brad Larson @.>; Comment @.> Subject: Re: [payloadcms/payload] Cannot build with dynamicIO enabled. (Issue #8897)
[https://avatars.githubusercontent.com/u/102186502?s=20&v=4]simovicaleksa left a comment (payloadcms/payload#8897)https://github.com/payloadcms/payload/issues/8897#issuecomment-2943755698
Still an issue as of writing this.
@jmikruthttps://github.com/jmikrut are there any plans of making PayloadCMS 3.0 compatible with dynamicIO before the official Next.js release that adopts it? use cache and dynamicIO make caching much easier and would really stack up with the existing PayloadCMS DX. Current Next.js docs also heavily imply that it will soon replace the old caching system.
— Reply to this email directly, view it on GitHubhttps://github.com/payloadcms/payload/issues/8897#issuecomment-2943755698, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAHCKWJGCKRFMHSYKBXYFP33CAQMPAVCNFSM6AAAAABQXVQWF2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDSNBTG42TKNRZHA. You are receiving this because you commented.Message ID: @.***>
Same issue for me. i moved over to next canary as i was sick of waiting for the new use cache, cachelife and cachetag functionality to come out. all of that works really well and seems stable so i expect it to be released to the main next release soon.
however, with the new use cache functionality, any use of headers(), cookies(), params, searchParams etc need to be inside a suspense boundary or it throws an error. ive sorted all the non payload side of my site and all works as expected, but im stuck as to how i can sort the payload admin side
is this being looked at yet. The use cache, cachelife and cachetag new features is the best thing next has added for a long time and really helps making caching a lot easier, so being able to use it with payload will be a big big help
You can use new 'use cache', cacheLife, cacheTag with latest payloadcms by enable experimental.useCache instead of dynamicIO.
Same issue for me. i moved over to next canary as i was sick of waiting for the new use cache, cachelife and cachetag functionality to come out. all of that works really well and seems stable so i expect it to be released to the main next release soon. however, with the new use cache functionality, any use of headers(), cookies(), params, searchParams etc need to be inside a suspense boundary or it throws an error. ive sorted all the non payload side of my site and all works as expected, but im stuck as to how i can sort the payload admin side is this being looked at yet. The use cache, cachelife and cachetag new features is the best thing next has added for a long time and really helps making caching a lot easier, so being able to use it with payload will be a big big help
You can use new
'use cache', cacheLife, cacheTagwith latest payloadcms by enableexperimental.useCacheinstead ofdynamicIO.
Wow you are right!
Just using useCache: true, and removing dynamicIO: true, from the experimental in next config worked
not a suspense needed or any payload admin errors
it works with 15.3.3 too, don't need canary. just set useCache:true and don't set dynamicIO:true
one thing to note, on development, if dev tools on the browser are open then it doesnt use the cahce and always gets fresh data which has thrown me in some of my testing thinking its not working, but when dev tools closed it works as expected on the standard 15.3.3 release
Same issue for me. i moved over to next canary as i was sick of waiting for the new use cache, cachelife and cachetag functionality to come out. all of that works really well and seems stable so i expect it to be released to the main next release soon. however, with the new use cache functionality, any use of headers(), cookies(), params, searchParams etc need to be inside a suspense boundary or it throws an error. ive sorted all the non payload side of my site and all works as expected, but im stuck as to how i can sort the payload admin side is this being looked at yet. The use cache, cachelife and cachetag new features is the best thing next has added for a long time and really helps making caching a lot easier, so being able to use it with payload will be a big big help
You can use new
'use cache', cacheLife, cacheTagwith latest payloadcms by enableexperimental.useCacheinstead ofdynamicIO.Wow you are right!
Just using useCache: true, and removing dynamicIO: true, from the experimental in next config worked
not a suspense needed or any payload admin errors
it works with 15.3.3 too, don't need canary. just set useCache:true and don't set dynamicIO:true
one thing to note, on development, if dev tools on the browser are open then it doesnt use the cahce and always gets fresh data which has thrown me in some of my testing thinking its not working, but when dev tools closed it works as expected on the standard 15.3.3 release
the problem with that is if you actually need dynamic IO...
yea, they are all coming together. there's really very little reason to utilize them individually as they are all going to ship together and likely be default.
I'll be honest, it's been painful getting our app compliant for ppr and dynamicIO, but it's cleaned up A LOT of anti-patterns and our app is much more performant and structured properly because of it.
yea, they are all coming together. there's really very little reason to utilize them individually as they are all going to ship together and likely be default.
I'll be honest, it's been painful getting our app compliant for ppr and dynamicIO, but it's cleaned up A LOT of anti-patterns and our app is much more performant and structured properly because of it.
yeah I agree. tbh they should have delayed app router until this came out. it was literally the missing piece. to work around this issue with payload I just went through and painstakingly added await connection() everywhere that needed ppr and was doing async data fetching.
So will Payload be ready to work with NextJS 16's "cacheComponents: true" flag when NextJS 16 drops? Or is all work waiting to start until it drops? Would like to try using this earlier in a beta version if possible.
So will Payload be ready to work with NextJS 16's "cacheComponents: true" flag when NextJS 16 drops? Or is all work waiting to start until it drops? Would like to try using this earlier in a beta version if possible.
You can use it now in next 15 if you turn the flag on. See https://simplesteps.guide/guides/technology/web-development/next-js-use-cache/use-cache
useCache on its own isn't the same as the new cacheComponents feature. ppr + dynamicIO (which are now by default enabled with cacheComponents) fail to build with payload because of the way it is handling dynamic pages.
useCache on its own isn't the same as the new cacheComponents feature. ppr + dynamicIO (which are now by default enabled with cacheComponents) fail to build with payload because of the way it is handling dynamic pages.
Agreed. I tried the canary with dynamicio and was a right effort to change things to just work with getting simple things like auth from a cookie. That will be a lot of work to fully support. However the use cache that is there is def worth using now imo as it makes it so much easier to make dynamic cache tags for clearing specific caches and its miles better than the unstable cache function that was the old way
So will Payload be ready to work with NextJS 16's "cacheComponents: true" flag when NextJS 16 drops? Or is all work waiting to start until it drops? Would like to try using this earlier in a beta version if possible.
You can use it now in next 15 if you turn the flag on. See https://simplesteps.guide/guides/technology/web-development/next-js-use-cache/use-cache
I know it works with Next 15 canary all right, but it doesn't work with Payload's admin screens. That was what I was inquiring about.
So will Payload be ready to work with NextJS 16's "cacheComponents: true" flag when NextJS 16 drops? Or is all work waiting to start until it drops? Would like to try using this earlier in a beta version if possible.
You can use it now in next 15 if you turn the flag on. See https://simplesteps.guide/guides/technology/web-development/next-js-use-cache/use-cache
I know it works with Next 15 canary all right, but it doesn't work with Payload's admin screens. That was what I was inquiring about.
The use cache, cache tag and cache life part does work with payload and doesn't need canary
I guess I’m talking about the /(payload)/admin/[[…segments]]/page.tsx file that throws a server error. How is that fixed without tinkering with the RootPage payload component that is returned by it, or that page.tsx file that is auto-generated (with the warning not to modify it?)
On Aug 2, 2025 at 2:46:53 PM, mustardpete @.***> wrote:
mustardpete left a comment (payloadcms/payload#8897) https://github.com/payloadcms/payload/issues/8897#issuecomment-3146716378
useCache on its own isn't the same as the new cacheComponents feature. ppr
- dynamicIO (which are now by default enabled with cacheComponents) fail to build with payload because of the way it is handling dynamic pages.
Agreed. I tried the canary with dynamicio and was a right effort to change things to just work with getting simple things like auth from a cookie. That will be a lot of work to fully support. However the use cache that is there is def worth using now imo as it makes it so much easier to make dynamic cache tags for clearing specific caches and its miles better than the unstable cache function that was the old way
— Reply to this email directly, view it on GitHub https://github.com/payloadcms/payload/issues/8897#issuecomment-3146716378, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEIG6K5YHU54GYLIMQRQRDT3LUPT3AVCNFSM6AAAAABQXVQWF2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTCNBWG4YTMMZXHA . You are receiving this because you commented.Message ID: @.***>
yeah I may have actually been too quick to blame payload. just tried a similar setup of dynamic root layout and dynamic root page (without payload) and im getting the same build error. I think its a next.js problem.
I guess I’m talking about the /(payload)/admin/[[…segments]]/page.tsx file
that throws a server error. How is that fixed without tinkering with the
RootPage payload component that is returned by it, or that page.tsx file
that is auto-generated (with the warning not to modify it?)
On Aug 2, 2025 at 2:46:53 PM, mustardpete @.***> wrote:
mustardpete left a comment (payloadcms/payload#8897)
https://github.com/payloadcms/payload/issues/8897#issuecomment-3146716378
useCache on its own isn't the same as the new cacheComponents feature. ppr
- dynamicIO (which are now by default enabled with cacheComponents) fail to
build with payload because of the way it is handling dynamic pages.
Agreed. I tried the canary with dynamicio and was a right effort to change
things to just work with getting simple things like auth from a cookie.
That will be a lot of work to fully support. However the use cache that is
there is def worth using now imo as it makes it so much easier to make
dynamic cache tags for clearing specific caches and its miles better than
the unstable cache function that was the old way
—
Reply to this email directly, view it on GitHub
https://github.com/payloadcms/payload/issues/8897#issuecomment-3146716378,
or unsubscribe
.
You are receiving this because you commented.Message ID:
@.***>
What I meant was the use cache without canary branch, with just experimental flag works fine with payload. With canary branch and turning on dynamicio there's and issue with payload as it's not wrapped in a suspense. You can use the new cache stuff without that and in standard 15 release not canary by just doing the experimental flag. As mentioned above look at https://simplesteps.guide/guides/technology/web-development/next-js-use-cache/use-cache it def works with payload ok
Gotcha. Thanks!
On Aug 2, 2025 at 3:33:58 PM, mustardpete @.***> wrote:
mustardpete left a comment (payloadcms/payload#8897) https://github.com/payloadcms/payload/issues/8897#issuecomment-3146736349
I guess I’m talking about the /(payload)/admin/[[…segments]]/page.tsx file
that throws a server error. How is that fixed without tinkering with the
RootPage payload component that is returned by it, or that page.tsx file
that is auto-generated (with the warning not to modify it?)
On Aug 2, 2025 at 2:46:53 PM, mustardpete @.***> wrote:
mustardpete left a comment (#8897 https://github.com/payloadcms/payload/issues/8897)
#8897 (comment) https://github.com/payloadcms/payload/issues/8897#issuecomment-3146716378
useCache on its own isn't the same as the new cacheComponents feature. ppr
- dynamicIO (which are now by default enabled with cacheComponents) fail to
build with payload because of the way it is handling dynamic pages.
Agreed. I tried the canary with dynamicio and was a right effort to change
things to just work with getting simple things like auth from a cookie.
That will be a lot of work to fully support. However the use cache that is
there is def worth using now imo as it makes it so much easier to make
dynamic cache tags for clearing specific caches and its miles better than
the unstable cache function that was the old way
—
Reply to this email directly, view it on GitHub
#8897 (comment) https://github.com/payloadcms/payload/issues/8897#issuecomment-3146716378 ,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AEIG6K5YHU54GYLIMQRQRDT3LUPT3AVCNFSM6AAAAABQXVQWF2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTCNBWG4YTMMZXHA
.
You are receiving this because you commented.Message ID:
@.***>
What I meant was the use cache without canary branch, with just experimental flag works fine with payload. With canary branch and turning on dynamicio there's and issue with payload as it's not wrapped in a suspense. You can use the new cache stuff without that and in standard 15 release not canary by just doing the experimental flag. As mentioned above look at https://simplesteps.guide/guides/technology/web-development/next-js-use-cache/use-cache it def works with payload ok
— Reply to this email directly, view it on GitHub https://github.com/payloadcms/payload/issues/8897#issuecomment-3146736349, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEIG6KYH4MOCTXH6EEXBA333LUVENAVCNFSM6AAAAABQXVQWF2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTCNBWG4ZTMMZUHE . You are receiving this because you commented.Message ID: @.***>