Set cookie within trpc

I'm using t3 and trpc and I have to set a cookie serverside, no errors happen, but the cookie is not included too. What is the correct way to set a cookie on a procedure?
21 Replies
mass
mass12mo ago
^ I've faced the same issue, started using pocketbase recently and I'm stuck looking for a way to set cookies inside tRPC routers
Endgame1013
Endgame101312mo ago
Are you using pages or app router?
Rafael Corrêa
Rafael Corrêa12mo ago
App router
Rafael Corrêa
Rafael Corrêa12mo ago
I know about this, but it wont work, trpc wont send the cookies
Endgame1013
Endgame101312mo ago
It should. Since you’re using the App directory, you may be able to set the cookie in the resHeaders prop in context. I’ve always used the cookies() function from Next and never had any problems.
Rafael Corrêa
Rafael Corrêa12mo ago
Its working when I use it outside of trpc (aka server actions), but somehow it wont work with trpc for me
Rafael Corrêa
Rafael Corrêa12mo ago
This is what Im doing to try to force the cookie, but its not saving
No description
Endgame1013
Endgame101312mo ago
Looks like you’re trying to set cookies on the client side in the links. You need to set the cookie in a procedure instead.
Rafael Corrêa
Rafael Corrêa12mo ago
this is the trpc/server.ts file I wouldnt be able to call this function from a client component
Endgame1013
Endgame101312mo ago
trpc/server.ts runs on the server, yes, but is still in the tRPC client code. If you want to set a cookie it needs to be done within a tRPC procedure so that the cookie is sent down to the client.
Rafael Corrêa
Rafael Corrêa12mo ago
and thats what im doing, the print shows me trying to bind the cookies to the headers
Endgame1013
Endgame101312mo ago
Respectfully, the code you posted is from a tRPC client. Cookies need to be set in a procedure.
Set up a tRPC Client | tRPC
1. Install the tRPC Client library
Endgame1013
Endgame101312mo ago
You should be doing something like this:
import { cookies } from “next/headers”;

const appRouter = router({
example: publicProcedure.mutation(async () => {
cookies().set(“foo”, “bar”);
return {
message: 'hello!',
};
}),
});
import { cookies } from “next/headers”;

const appRouter = router({
example: publicProcedure.mutation(async () => {
cookies().set(“foo”, “bar”);
return {
message: 'hello!',
};
}),
});
shmookoff
shmookoff12mo ago
Hey, @Rafael Corrêa. I was stuck at this too minutes ago until I experienced the 'Uh' moment. In t3 by default, react's client is configured with unstable_httpBatchStreamLink (the requests are batched and streamed in as they are completed) https://trpc.io/docs/client/links/httpBatchStreamLink. Because of streaming, the response is already sent by the time a cookie is set. This is why you can't set a cookie in RSC. Basically, there're two (reasonable) ways: either give up on streaming and use a different link or don't use trpc for operations that require setting a cookie. I'm going with the first way as I don't think streaming will provide much benefit in my case. For that, just replace unstable_httpBatchStreamLink in react's trpc client with httpBatchLink https://trpc.io/docs/client/links/httpBatchLink Let me know if that helps you I suppose you can create a separate trpc client with a link that is not streamed, and use it for those operations. That's too much hassle for my taste though.
boonguy
boonguy11mo ago
Thank you for this, cleared up a bunch for me. Also solved the cookie problem I was experiencing.
shmookoff
shmookoff11mo ago
Awesome! Thanks for letting me know ❤️
Hosenur
Hosenur7mo ago
@shmookoff I am using pages router , and facing the same issue, httpBatchLink is also set, I get the error : tRPC failed on auth.register: cookies was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context
shmookoff
shmookoff7mo ago
I'm no expert on pages router, but I think I can look into that. Could you please share the code?
Hosenur
Hosenur7mo ago
Here is the code for server/api/trpc.ts
import { initTRPC } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
import superjson from "superjson";
import { ZodError } from "zod";
import { db } from "~/server/db";
type CreateContextOptions = Record<string, never>;
const createInnerTRPCContext = (_opts: CreateContextOptions) => {
return {
db,
};
};
export const createTRPCContext = (_opts: CreateNextContextOptions) => {
return createInnerTRPCContext({});
};
const t = initTRPC.context<typeof createTRPCContext>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
export const createCallerFactory = t.createCallerFactory;
export const createTRPCRouter = t.router;
export const publicProcedure = t.procedure;
import { initTRPC } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
import superjson from "superjson";
import { ZodError } from "zod";
import { db } from "~/server/db";
type CreateContextOptions = Record<string, never>;
const createInnerTRPCContext = (_opts: CreateContextOptions) => {
return {
db,
};
};
export const createTRPCContext = (_opts: CreateNextContextOptions) => {
return createInnerTRPCContext({});
};
const t = initTRPC.context<typeof createTRPCContext>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
export const createCallerFactory = t.createCallerFactory;
export const createTRPCRouter = t.router;
export const publicProcedure = t.procedure;
@shmookoff
shmookoff
shmookoff7mo ago
Thanks. Could you please send from where the error is thrown? The error says that it originates from auth.register handler and specifies that cookies was called outside of a request scope. I would like to see the code where cookies was used. @Hosenur The docs does not include cookies under functions in Pages Router. I suppose, you would need to use some other function.
Want results from more Discord servers?
Add your server