Next.js Discord

Discord Forum

Cookies in a server action

Unanswered
coder2000 posted this in #help-forum
Open in Discord
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.