Error: Cookies can only be modified in a Server Action... but it is a server action?
Answered
David L. Bowman posted this in #help-forum
I cannot seem to delete all my cookies from a server action, I get the following error:
[ Server ] Error: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#options
// page.tsx
import { CreatePatientForm } from "@/components/CreatePatientForm";
import { deleteAllCookies } from "@/lib/next/deleteAllCookies";
export default async function Home() {
await deleteAllCookies();
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
// deleteAllCookies.ts
"use server";
import { cookies } from "next/headers";
export async function deleteAllCookies() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
}
Answered by B33fb0n3
when fetching your own endpoints inside a server component, you need to provide the full url from the api route instead of a relative url like you doing rn
In every case it's not recommended to fetch your own api routes. You want to delete all your cookies now. Why you would want to do that is unclear to me. It is not recommended. For more information read this: https://nextjs-faq.com/fetch-api-in-rsc
In every case it's not recommended to fetch your own api routes. You want to delete all your cookies now. Why you would want to do that is unclear to me. It is not recommended. For more information read this: https://nextjs-faq.com/fetch-api-in-rsc
20 Replies
@David L. Bowman I cannot seem to delete all my cookies from a server action, I get the following error: `[ Server ] Error: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#options`
tsx
// page.tsx
import { CreatePatientForm } from "@/components/CreatePatientForm";
import { deleteAllCookies } from "@/lib/next/deleteAllCookies";
export default async function Home() {
await deleteAllCookies();
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
tsx
// deleteAllCookies.ts
"use server";
import { cookies } from "next/headers";
export async function deleteAllCookies() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
}
when you calling your server action inside a server component, the server action will be translated to a normal function. And with that it's just a normal function.
You can only modify your cookies inside a server action or route handler. So do that and you will be good to go
You can only modify your cookies inside a server action or route handler. So do that and you will be good to go
@B33fb0n3 when you calling your server action inside a server component, the server action will be translated to a normal function. And with that it's just a normal function.
You can only modify your cookies inside a server action or route handler. So do that and you will be good to go
Hmmm, that makes sense. Although, when I try to manipulate the cookies directly within the server component
/page.tsx
I get the same error:"use server";
import { CreatePatientForm } from "@/components/CreatePatientForm";
import { cookies } from "next/headers";
export default async function Home() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
@David L. Bowman Hmmm, that makes sense. Although, when I try to manipulate the cookies directly within the server component `/page.tsx` I get the same error:
tsx
"use server";
import { CreatePatientForm } from "@/components/CreatePatientForm";
import { cookies } from "next/headers";
export default async function Home() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
yea, beeing inside a server component doesn't mean, that you are inside a server action or route handler.
You need to be inside a server action (call a server function from the client for example) or use a route handler
You need to be inside a server action (call a server function from the client for example) or use a route handler
@B33fb0n3 yea, beeing inside a server component doesn't mean, that you are inside a server action or route handler.
You need to be inside a server action (call a server function from the client for example) or use a route handler
I'm sorry, I don't understand. Could you tell me what I'm doing wrong? When I look at the documentation, it looks like I'm doing nearly the exact same thing.
import { CreatePatientForm } from "@/components/CreatePatientForm";
import { cookies } from "next/headers";
export default async function Home() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
Maybe it doesn't like my delete function.
@David L. Bowman I'm sorry, I don't understand. Could you tell me what I'm doing wrong? When I look at the documentation, it looks like I'm doing nearly the exact same thing.
tsx
import { CreatePatientForm } from "@/components/CreatePatientForm";
import { cookies } from "next/headers";
export default async function Home() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
you are right, you doing nearly exactly what's written down. There is one difference:
Server components: READ cookies (modifications are NOT allowed)
Server action or route handler: READ, MODIFY cookies (modifications are allowed)
What do you need to do?
Remove the deletion (modify) of your cookies.
Server components: READ cookies (modifications are NOT allowed)
Server action or route handler: READ, MODIFY cookies (modifications are allowed)
What do you need to do?
Remove the deletion (modify) of your cookies.
@B33fb0n3 you are right, you doing nearly exactly what's written down. There is one difference:
Server components: READ cookies (modifications are **NOT** allowed)
Server action or route handler: READ, MODIFY cookies (modifications are allowed)
What do you need to do?
Remove the deletion (modify) of your cookies.
Okay, that makes sense. Then... how do I delete my cookies? When I try to call a server action like:
From within the
"use server";
import { cookies } from "next/headers";
export async function deleteAllCookies() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
}
From within the
/page.tsx
it doesn't work. Where am I supposed to call this function?I really appreciate your help btw.
@David L. Bowman Okay, that makes sense. Then... how do I delete my cookies? When I try to call a server action like:
tsx
"use server";
import { cookies } from "next/headers";
export async function deleteAllCookies() {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
}
From within the `/page.tsx` it doesn't work. Where am I supposed to call this function?
don't use a server action here as it will be automatically translated to a normal function. Use a route handler instead
@B33fb0n3 don't use a server action here as it will be automatically translated to a normal function. Use a route handler instead
Okay, so... this may be the last thing, and I appreciate you teaching me.
Here's my
Here's my
/app/api/deleteAllCookies/route.ts
import { cookies } from "next/headers";
export async function DELETE(request: Request) {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
return new Response("Cookies Deleted", {
status: 200,
});
}
// page.tsx
import { CreatePatientForm } from "@/components/CreatePatientForm";
export default async function Home() {
await fetch("/api/deleteAllCookies", {
method: "DELETE",
});
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
@David L. Bowman Okay, so... this may be the last thing, and I appreciate you teaching me.
Here's my `/app/api/deleteAllCookies/route.ts`
ts
import { cookies } from "next/headers";
export async function DELETE(request: Request) {
const cookieStore = await cookies();
for (const cookie of cookieStore.getAll()) {
cookieStore.delete(cookie.name);
}
return new Response("Cookies Deleted", {
status: 200,
});
}
tsx
// page.tsx
import { CreatePatientForm } from "@/components/CreatePatientForm";
export default async function Home() {
await fetch("/api/deleteAllCookies", {
method: "DELETE",
});
return (
<main className="min-h-screen flex items-center justify-center bg-gray-100">
<CreatePatientForm />
</main>
);
}
when fetching your own endpoints inside a server component, you need to provide the full url from the api route instead of a relative url like you doing rn
In every case it's not recommended to fetch your own api routes. You want to delete all your cookies now. Why you would want to do that is unclear to me. It is not recommended. For more information read this: https://nextjs-faq.com/fetch-api-in-rsc
In every case it's not recommended to fetch your own api routes. You want to delete all your cookies now. Why you would want to do that is unclear to me. It is not recommended. For more information read this: https://nextjs-faq.com/fetch-api-in-rsc
Answer
@B33fb0n3 when fetching your own endpoints inside a server component, you need to provide the full url from the api route instead of a relative url like you doing rn
In every case it's *not* recommended to fetch your own api routes. You want to delete all your cookies now. Why you would want to do that is unclear to me. It is **not recommended**. For more information read this: https://nextjs-faq.com/fetch-api-in-rsc
Thank you, you taught me a lot of things, This works perfectly for me now.
I'm creating a demo app for a client, and I need them to reset their cookies every time they start the app.
Honestly, i should have just created a db.
Maybe this is still bad practice.
@David L. Bowman I'm creating a demo app for a client, and I need them to reset their cookies every time they start the app.
then it's the best to create a page.tsx for that that imports a client component with a button "clear all cookies". On the button click a server action will be called to delete all cookies.
As the server action is called from a client component, the server action works fine. It also doesn't happen on every request then
As the server action is called from a client component, the server action works fine. It also doesn't happen on every request then
happy to help
i appreciated learning more about this though 🙂