Rule
Rule2w ago

tRPC 404 in Next.js API Routes

I'm trying to upgrade my Next.js version to 15 and still use tRPC with API route. I'm getting 404 for all trpc api routes. Is anyone else facing the same issue? All the other api routes are working fine. app/api/trpc/[trpc]/route.ts
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";

import { appRouter } from "./trpc";

const handler = async (request: Request) => {
return await fetchRequestHandler({
endpoint: "/api/trpc",
req: request,
router: appRouter,
onError: (opts) => {
console.error(`[${opts.error.code}] ${opts.path}:`, opts.error);
},
});
};

export const GET = handler;
export const POST = handler;
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";

import { appRouter } from "./trpc";

const handler = async (request: Request) => {
return await fetchRequestHandler({
endpoint: "/api/trpc",
req: request,
router: appRouter,
onError: (opts) => {
console.error(`[${opts.error.code}] ${opts.path}:`, opts.error);
},
});
};

export const GET = handler;
export const POST = handler;
trpc.ts
import { initTRPC } from "@trpc/server";

const t = initTRPC.create();
export const router = t.router;
export const publicProcedure = t.procedure;
export const appRouter = router({
hello: publicProcedure.query(async () => {
return "world";
}),
});
import { initTRPC } from "@trpc/server";

const t = initTRPC.create();
export const router = t.router;
export const publicProcedure = t.procedure;
export const appRouter = router({
hello: publicProcedure.query(async () => {
return "world";
}),
});
5 Replies
Michael Schaufelberger
If you console.log at the line above awaiting the fetchRequestHandler, does it log anything? Also, I have a createContext for the fetchRequestHandler - maybe that's needed?
Rule
RuleOP2w ago
It doesnt log anything. If I remove the fetchRequestHandler completely and leave the console.log there, it logs.
Michael Schaufelberger
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';

import { createContext } from '../server/context';
import { appRouter } from '../server/router';

export const maxDuration = 60; // seconds
export const dynamic = 'force-dynamic';

const handler = (req: Request) =>
fetchRequestHandler({
endpoint: '/api/trpc',
req,
router: appRouter,
createContext,
});

export { handler as GET, handler as POST };
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';

import { createContext } from '../server/context';
import { appRouter } from '../server/router';

export const maxDuration = 60; // seconds
export const dynamic = 'force-dynamic';

const handler = (req: Request) =>
fetchRequestHandler({
endpoint: '/api/trpc',
req,
router: appRouter,
createContext,
});

export { handler as GET, handler as POST };
that's my working file. Could you try to alter it to use your imports/naming but keep the exports and other function definitions? Maybe something strange regarding the handler refs, etc. is happening? I feel like I'm missing something obvious... 😅 and remove the createContext from mine. i think that's optional
Rule
RuleOP2w ago
Sorry I should probably have put the full code, I needed to make is more simple since it's related to work and it's private. I found the reason from createContext :D we are passing google cloud task client to the context which is for some reason causing it
Michael Schaufelberger
That's fine. Glad I could help!