Cookies in a server action
Unanswered
coder2000 posted this in #help-forum
I have a server action that calls a method that sets a cookie. I keep getting an error saying that only a server action or route handler can set cookies. Is it not possible to delegate this to another method?
7 Replies
Asian black bear
You are getting this error because you're presumably attempting to invoke it during the render of a server components which is not possible.
In that context the error message means that cookies can only be set by client calls to a route handler or server action.
It is in a form action
import { caller } from "@/components/trpc/server";
import { LoginForm } from "@/components/user/login-form";
import {
createSession,
generateSessionToken,
getCurrentSession,
setSessionTokenCookie,
} from "@/lib/auth/sessions";
import Image from "next/image";
import { redirect } from "next/navigation";
import logo from "./symbol-color.svg";
export default async function LoginPage() {
const { session, user } = await getCurrentSession();
if (session !== null) {
if (!user.emailVerified) {
redirect("/verify-email");
}
if (!user.totpKey) {
redirect("/2fa/setup");
}
redirect("/");
}
const authenticateUserAction = async (formData: FormData) => {
"use server";
const email = formData.get("email") as string;
const password = formData.get("password") as string;
const user = await caller.users.authenticate({ email, password });
const sessionToken = generateSessionToken();
const session = createSession(sessionToken, user.id, {
twoFactorVerified: false,
});
setSessionTokenCookie(sessionToken, session.expiresAt);
if (!user.emailVerified) {
redirect("/verify-email");
}
if (!user.totpKey) {
redirect("/2fa/setup");
}
redirect("/2fa");
};
return (
<div className="flex h-screen flex-col items-center justify-center">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<Image alt="TradeCrews" src={logo} className="mx-auto h-16 w-auto" />
<h2 className="mt-6 text-center font-bold text-2xl/9 text-gray-900 tracking-tight dark:text-gray-200">
Login
</h2>
</div>
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
<div className="px-6 py-12 shadow-sm sm:rounded-lg sm:px-12 dark:shadow-tc-orange/50">
<LoginForm authenticateUserAction={authenticateUserAction} />
</div>
</div>
</div>
);
}
It works if I put the cookie code directly in the action but not if I use a method to call it.
Asian black bear
It's not unheard of that the heuristics for extract server actions are not perfect. Personally speaking I have never defined an action in the same component and typically just define them in their separate file and never had issues.
I had it in a separate file but was getting the same issue. I'll try that again and see.