vercel / next.js

The React Framework
https://nextjs.org
MIT License
124.87k stars 26.66k forks source link

App Router 14.2.5 Setting a cookie in a Server Action Failing #68206

Open lukebelbina opened 1 month ago

lukebelbina commented 1 month ago

Link to the code that reproduces this issue

https://github.com/lukebelbina/nextjs-cookie-server-action-bug

To Reproduce

Create the following Page in Next Js 14.2.5.

'use server'

export default async function Page() {
  async function setCookieServerAction(signInToken?: string) {
    'use server';

    cookies().set('test', '1234', {});
  }

  await setCookieServerAction();

  return <></>;
}

Navigate to the page and you should see the error:

Error: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options

I have tried a bunch of different ways to do this based on the documentation but all of the result in the same error. My understanding is this is a server action. I also tried a route.

Current vs. Expected behavior

Expect the cookie to be set

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP PREEMPT_DYNAMIC Wed, 24 Jul 2024 22:25:43 +0000
  Available memory (MB): 127918
  Available CPU cores: 32
Binaries:
  Node: 22.4.1
  npm: 10.8.1
  Yarn: N/A
  pnpm: 9.5.0
Relevant Packages:
  next: 14.2.5 // Latest available version is detected (14.2.5).
  eslint-config-next: 14.2.5
  react: 18.3.1
  react-dom: 18.3.1
  typescript: 5.5.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Not sure

Which stage(s) are affected? (Select all that apply)

next dev (local), next start (local)

Additional context

No response

AliRazaDev27 commented 1 month ago

Hi, first of all there is a logical problem with your code, against whom do you want to set the cookie? (who is the client ). Since the location you are executing the code is your '/' route (app/page.tsx) file, the code will be statically generated on compile thus your self-invoking function setCookieServerAction will also be executed(from the server), you can see an error message in your server console telling that you can only modify (set) the cookies from server actions or route handlers, what this means is that putting "use server" in a route page does not make it a server action, extract your server action function and make a new file for your server actions only, usually at lib/actions.js (with "use server"),This file only exports the server actions and has no rendering logic unlike the route pages. Another thing is that you should call the server action from a client component, either using controlled method like button onClick or useEffect on mount.

AliRazaDev27 commented 1 month ago

image