vercel / next.js

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

[NEXT-1090] Property 'set' does not exist on type 'ReadonlyRequestCookies'. #49259

Closed pedro757 closed 1 year ago

pedro757 commented 1 year ago

Verify canary release

Provide environment information

Operating System:
      Platform: linux
      Arch: x64
      Version: #1 SMP PREEMPT_DYNAMIC Thu Apr  6 19:47:04 UTC 2023
    Binaries:
      Node: 18.16.0
      npm: 9.5.1
      Yarn: 1.22.19
      pnpm: 8.3.1
    Relevant packages:
      next: 13.4.1-canary.1
      eslint-config-next: 13.4.1-canary.1
      react: 18.2.0
      react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

No response

Link to the code that reproduces this issue

https://codesandbox.io/p/sandbox/divine-firefly-4si8qm?file=%2Fpackage.json

To Reproduce

https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions#using-headers

Describe the Bug

The docs state that we can set cookies within a server action. but it's readonly

image

https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions#using-headers

Expected Behavior

I want to be able to do what the docs says: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions#using-headers

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

NEXT-1090

BoraALAP commented 1 year ago

is there any update on this ??

kristian240 commented 1 year ago

Seems to be working on v13.4.1

borispoehland commented 1 year ago

Seems to be working on v13.4.1

I'm using 13.4.1 and for me it's not working

ZeroThe2nd commented 1 year ago

Just like @borispoehland, for me I'm also getting the error that .set() does not exist in cookies() imported as the example referred to in the original post linked.

I have the serverActions: true flag on, running yarn next --version reports Next.js v13.4.1. I've also tried removing node_modules and doing a yarn upgrade just to be sure.

Whenever I invoke cookies().set(...) from a server action, the following error appears in my terminal:

image

Maybe this gives more of a lead?

Edit: This instance of cookies().set() is being called in a server action which is housed in an external file, that has 'use server' as it's first line. The component it's being imported into is by itself not a client component, but one of its parent components is. This might actually be related to the issue at hand in my case.

slacerda85 commented 1 year ago

I'm still having the same problem, but I noticed in the .pnpm file for the definitions, that the set value was omitted in the Typescript utility:

/// <reference types="node" /> import type { RequestCookies } from '../cookies'; import type { BaseNextResponse } from '../../../base-http'; import type { ServerResponse } from 'http'; import { ResponseCookies } from '../cookies'; export declare type ReadonlyRequestCookies = Omit<RequestCookies, 'clear' | 'delete' | 'set'>; export declare class RequestCookiesAdapter { static seal(cookies: RequestCookies): ReadonlyRequestCookies; } export declare const SYMBOL_MODIFY_COOKIE_VALUES: unique symbol; export declare class MutableRequestCookiesAdapter { static seal(cookies: RequestCookies, res: ServerResponse | BaseNextResponse | undefined): ResponseCookies; }

maybe is something with those definitions, I dont know...

DanieleSidoti commented 1 year ago

I have the same problem

mrob11 commented 1 year ago

cookies().set is working for me in a server action using the next@13.4.2-canary.2

suhascv commented 1 year ago

cookies().set using Next.js v13.4.2-canary.2 in server action doesn't work for me

Error: ReadonlyRequestCookies cannot be modified.
johnson-jesse commented 1 year ago

cookies().set is working for me in a server action using the next@13.4.2-canary.2

✅ Confirmed. This is working in 13.4.2-canary.2 and 13.4.2-canary.3. The typescript error still shows, but the app should still work. I no longer see the runtime error as show above.

Error: Invariant: Method expects to have requestAsyncStorage, none available at persistCookieState

I see the cookie set in the browser as expected via server action. Now if we can just get that TS error and the rest of those console warnings cleaned up, we'll be a happy crew.

ma13gagan commented 1 year ago

Edit: This instance of cookies().set() is being called in a server action which is housed in an external file, that has 'use server' as it's first line. The component it's being imported into is by itself not a client component, but one of its parent components is. This might actually be related to the issue at hand in my case.

Looks like we cannot use cookies in the Server Action if that Server Action is directly imported into the Client Component. I made it work by importing that Server Action in the Server Component first and then passing it as a prop in the Client Component. I don't know if it is the right way to achieve this.

Edit: Cookies work in Server Actions when directly imported into Client Components in version 13.4.2-canary.3. But TS error is still there.

shuding commented 1 year ago

This should be a TypeScript error as the .set method is missing. If you add // @ts-ignore it should pass build with latest canary version.

Will find a way to fix it properly.

mrob11 commented 1 year ago

This should be a TypeScript error as the .set method is missing. If you add // @ts-ignore it should pass build with latest canary version.

Will find a way to fix it properly.

Adding the @ts-ignore directive is allowing my build to pass now. Great! Looking forward to proper support.

itsgoofer commented 1 year ago

I'm on 13.4.1 and can confirm that, even though vscode is complaining, .set works just fine. However, building your project with yarn build throws the same error. Using // @ts-ignore gets you through building tho.

maninderpreetsingh commented 1 year ago

I tried on 13.4.1 by // @ts-ignore but after the build and starting project it's thorwing error! ReadonlyRequestCookiesError: ReadonlyRequestCookies cannot be modified.

itsgoofer commented 1 year ago

I tried on 13.4.1 by // @ts-ignore but after the build and starting project it's thorwing error! ReadonlyRequestCookiesError: ReadonlyRequestCookies cannot be modified.

Make sure you are using "use server" wherever you're using cookies().set. That can be in an action or an api route.

maninderpreetsingh commented 1 year ago

I tried but still the cookie is not set and getting error "error unhandledRejection: Error: ReadonlyRequestCookies cannot be modified." on SSR. Also tried on canary build as well!

anneau commented 1 year ago

Same problem.

https://github.com/vercel/next.js/blob/062fbf6d2d1629ffa240b87af35955c51f5eaeaa/packages/next/src/client/components/headers.ts#L40-L47

It seems like it's being done intentionally...

john-griffin commented 1 year ago

Setting a cookie in a server action (dedicated server action file) triggered from a server component form action I get:

error Error: Invariant: Method expects to have requestAsyncStorage, none available

in next 13.4.2

john-griffin commented 1 year ago

Thanks for fixing the type but has anyone actually got this working in a server action file? The updated type error and docs suggest this is possible but I always get error Error: Invariant: Method expects to have requestAsyncStorage, none available.

johnson-jesse commented 1 year ago

Yes. See thread above

Sent from Proton Mail for iOS

On Mon, May 15, 2023 at 11:51 AM, John Griffin @.***(mailto:On Mon, May 15, 2023 at 11:51 AM, John Griffin < wrote:

Thanks for fixing the type but has anyone actually got this working in a server action file? The updated type error and docs suggest this is possible but I always get error Error: Invariant: Method expects to have requestAsyncStorage, none available.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.***>

john-griffin commented 1 year ago

Ok I believe the confusion is between imported server action files vs in component server actions.

This currently works fine for inline server actions where use server directive is at the top of the function body.

It throws the requestAsyncStorage error for actions defined with top-level use server directive on top of a file.

johnson-jesse commented 1 year ago

@john-griffin Does this example repo I just set up help? https://github.com/johnson-jesse/next-server-action-cookies-demo

josias-r commented 1 year ago

Also experiencing this error in a simple server action file smth like:

"use server";

export async function myAction() {
   cookies().set(...); // TS Error
}

Relying on a // @ts-expect-error comment for now :)

john-griffin commented 1 year ago

@johnson-jesse thanks, so it seems like you are triggering the file based server action from a client component using an onClick. This is not the exact case I have. It errors with requestAsyncStorage when it's a server component triggering via <form action=.

johnson-jesse commented 1 year ago

@john-griffin Sure, I've updated my repo example https://github.com/johnson-jesse/next-server-action-cookies-demo to also show it working with server component and formAction. Let me know how that works for you please.

john-griffin commented 1 year ago

@johnson-jesse thats working great! I paired my example down to match and it seems ok now. It seems like something was being cached somewhere. Cheers!

john-griffin commented 1 year ago

@johnson-jesse actually I found the issue now.

I have another separate client component referencing the same actions file but a different action in that file.

Removing this form stops the requestAsyncStorage error from the first component.

It seems like if you have some client components and some server components calling into different server actions in the same file this issue will happen.

johnson-jesse commented 1 year ago

@john-griffin Not sure I follow. But you're working so we're good. 😎 I updated my repo with more examples of some cross usage.

sujang958 commented 1 year ago

What about setting Http-only cookies? How do I set Http-only cookies?

josias-r commented 1 year ago

What about setting Http-only cookies? How do I set Http-only cookies?

Noticed the same, some types exist, but they are not fully correct. httpOnly, expiry date for example are missing :D

I think this issue shold be reopened

johnson-jesse commented 1 year ago

What about setting Http-only cookies? How do I set Http-only cookies?

@sujang958 You'll have to move to latest release https://github.com/vercel/next.js/releases/tag/v13.4.4-canary.0

And @josias-r no, it shouldn't be reopened.

deeq14 commented 1 year ago

I'm getting "Error: Invariant: Method expects to have requestAsyncStorage, none available"

This happens when client component is calling an action from separate file with the "use server" directive at the top of the file like @john-griffin said

It works with no issue IF the page is server rendered and not using "use client"

github-actions[bot] commented 1 year ago

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.