最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Error: Dynamic server usage: headers on Next 13.4 - Stack Overflow

programmeradmin1浏览0评论

This is the function generating the error. It's a simple function to get the token from the session

  4 | 
  5 | export async function getUserToken() {
> 6 | const session = await getServerSession(authOptions)
    |                                       ^
  7 | 
  8 | return session?.user?.token
  9 | }

I've been struggling for a couple days trying to figure out what is the issue. So far I have managed to isolate it to layout & page RSC that try to make us of next-auths getServerSession. I need to be able to pass the session to make request on my backend and whenever I try to populate a client component with api calls that need the session the error is thrown.

Any insights or recommended workaround available?

Here is the main layout that needs the request to fill the TeamSwitcher

export default async function RootLayout({ children, params: { lng } }: Props) {
  const clients = await getClients()
  return (
    <>
      <div className="flex flex-col">
        <div className="border-b">
          <div className="flex h-16 items-center px-4">
            {/* @ts-expect-error Server Component */}
            <MainNav
              lng={lng}
              title={siteConfig.name}
              items={siteConfig.mainNav}
            />
            <div className="ml-auto flex items-center space-x-4">
              <TeamSwitcher clients={clients} />
              {/* @ts-expect-error Server Component */}
              <UserNav lng={lng} user={user} />
            </div>
          </div>
        </div>
        {children}
      </div>
    </>
  )
}

This is the api call, everything pretty straightforward

export async function getClients(): Promise<Client[]> {
  const token = await getUserToken()

  if (!token) throw Error("Missing token for request")

  return await api
    .headers({
      accept: "application/json",
      token,
    })
    .get("/clients")
    .json()
}

This is the function generating the error. It's a simple function to get the token from the session

  4 | 
  5 | export async function getUserToken() {
> 6 | const session = await getServerSession(authOptions)
    |                                       ^
  7 | 
  8 | return session?.user?.token
  9 | }

I've been struggling for a couple days trying to figure out what is the issue. So far I have managed to isolate it to layout & page RSC that try to make us of next-auths getServerSession. I need to be able to pass the session to make request on my backend and whenever I try to populate a client component with api calls that need the session the error is thrown.

Any insights or recommended workaround available?

Here is the main layout that needs the request to fill the TeamSwitcher

export default async function RootLayout({ children, params: { lng } }: Props) {
  const clients = await getClients()
  return (
    <>
      <div className="flex flex-col">
        <div className="border-b">
          <div className="flex h-16 items-center px-4">
            {/* @ts-expect-error Server Component */}
            <MainNav
              lng={lng}
              title={siteConfig.name}
              items={siteConfig.mainNav}
            />
            <div className="ml-auto flex items-center space-x-4">
              <TeamSwitcher clients={clients} />
              {/* @ts-expect-error Server Component */}
              <UserNav lng={lng} user={user} />
            </div>
          </div>
        </div>
        {children}
      </div>
    </>
  )
}

This is the api call, everything pretty straightforward

export async function getClients(): Promise<Client[]> {
  const token = await getUserToken()

  if (!token) throw Error("Missing token for request")

  return await api
    .headers({
      accept: "application/json",
      token,
    })
    .get("/clients")
    .json()
}
Share Improve this question asked May 18, 2023 at 23:37 Dan CastrilloDan Castrillo 811 gold badge1 silver badge4 bronze badges 2
  • i've exactly the same error but in a different usecase. i'm checking if the token exists in a server component (using getServerSession) to perform redirections (index to sign-in if not signed, etc). also confused by the error overall, i've no idea why it breaks. – y_nk Commented May 19, 2023 at 6:11
  • Yeah so far my solution has been to remove getStaticProps but I'm still not sure I understand the issue. Seems to me that is related to static to dynamic rendering but I can't find any documentation that explains it very clearly – Dan Castrillo Commented May 20, 2023 at 0:41
Add a comment  | 

4 Answers 4

Reset to default 12

Add

export const dynamic = "force-dynamic"

to where you getServerSession, Page, Layout, or Route Handler。

If you are using this api directly and not in the Route Hander, then you need to add the above code to every page that calls it, whereas if you call it from within a component it will not work according to the documentation. So if you need to use it multiple times then Route Hander is a better choice.

Office doc

Server rendering usually happens in one place, so fetching data associated with a user needs to be known to be dynamic.

Dynamic routes occur after fetching some data, Next cannot directly generate the corresponding page or content, so the same needs to be specified dynamically.

Possible solutions that I found:

  • export const dynamic = "force-dynamic"
  • export const revalidate = 0
  • insert "use server" on the top of the file

But, none of those solutions worked for me, after some time I discovered that if the cookie or headers are called inside a try-catch it will generate this error.

Solutions:

  • put the calling of the cookie and/or headers functions outside of the try-catch

Updates:

2023-02-12

Some people use libraries (such as supabase) that get cookies in the background, and it is necessary to put some callers outside try-catch to avoid this issue also.

I've found I get this error when using these functions with static generation - and only while using the dev server, not sure if that's what you're experiencing.

If you're having trouble only with the dev server but still want to statically generate your pages for production (my case) you can add the following to any routes that use generateStaticParams AND call these functions:

// what used to be export function generateStaticParams
function staticParams(){
...
}

// fix "dynamic server usage" errors in dev mode by turning off static generation and forcing dynamic rendering
export const generateStaticParams =  process.env.NODE_ENV === "production" ? staticParams :  undefined;
export const dynamic =  process.env.NODE_ENV === "production" ? 'auto' : 'force-dynamic';

This is probably not the answer you're looking for, but for some reason i had the same issue (see the comment on your post).


I've found a way to bypass this. It's not ideal, but kudos to https://github.com/vercel/next.js/issues/48979#issuecomment-1539961418 who points out https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config

From the error stack I had, I could see the same error as yours, but also something earlier mentioning "static rendering".

You can add export const dynamic = 'force-dynamic'; to avoid static pre-rendering at build, which should probably do the trick (it did for me).

发布评论

评论列表(0)

  1. 暂无评论