Question:
I’m encountering an issue with my Next.js application where I’m trying to use tRPC for API handling. I’m getting the following error:
<code>Error: Unable to find tRPC Context. Did you forget to wrap your App inside `withTRPC` HoC?
</code>
<code>Error: Unable to find tRPC Context. Did you forget to wrap your App inside `withTRPC` HoC?
</code>
Error: Unable to find tRPC Context. Did you forget to wrap your App inside `withTRPC` HoC?
Error Details:
<code>Unhandled Runtime Error
Error: Unable to find tRPC Context. Did you forget to wrap your App inside `withTRPC` HoC?
Source
srcappauth-callbackpage.tsx (11:69) @ useQuery
9 | const origin = searchParams.get('orogin')
10 |
> 11 | const {data, isLoading, isError, isSuccess} = trpc.authCallback.useQuery();
| ^
12 | if (isSuccess) {
13 | // user is synced to db
14 | router.push(origin ? `/${origin}` : '/dashboard')
</code>
<code>Unhandled Runtime Error
Error: Unable to find tRPC Context. Did you forget to wrap your App inside `withTRPC` HoC?
Source
srcappauth-callbackpage.tsx (11:69) @ useQuery
9 | const origin = searchParams.get('orogin')
10 |
> 11 | const {data, isLoading, isError, isSuccess} = trpc.authCallback.useQuery();
| ^
12 | if (isSuccess) {
13 | // user is synced to db
14 | router.push(origin ? `/${origin}` : '/dashboard')
</code>
Unhandled Runtime Error
Error: Unable to find tRPC Context. Did you forget to wrap your App inside `withTRPC` HoC?
Source
srcappauth-callbackpage.tsx (11:69) @ useQuery
9 | const origin = searchParams.get('orogin')
10 |
> 11 | const {data, isLoading, isError, isSuccess} = trpc.authCallback.useQuery();
| ^
12 | if (isSuccess) {
13 | // user is synced to db
14 | router.push(origin ? `/${origin}` : '/dashboard')
Relevant Code:
src/app/layout.tsx
:
<code>import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { cn } from "@/lib/utils";
import Navbar from "@/components/Navbar";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" className="light">
<body className={cn(
'min-h-screen font-sans antialiased grainy',
inter.className
)}>
<Navbar />
{children}
</body>
</html>
);
}
</code>
<code>import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { cn } from "@/lib/utils";
import Navbar from "@/components/Navbar";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" className="light">
<body className={cn(
'min-h-screen font-sans antialiased grainy',
inter.className
)}>
<Navbar />
{children}
</body>
</html>
);
}
</code>
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { cn } from "@/lib/utils";
import Navbar from "@/components/Navbar";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" className="light">
<body className={cn(
'min-h-screen font-sans antialiased grainy',
inter.className
)}>
<Navbar />
{children}
</body>
</html>
);
}
src/app/_trpc/config.ts
:
<code>import { AppRouter } from '@/trpc';
import { withTRPC } from '@trpc/next';
function getBaseUrl() {
if (typeof window !== 'undefined') {
return '';
}
if (process.env.VERCEL_URL) {
return `https://${process.env.VERCEL_URL}`;
}
return `http://localhost:${process.env.PORT ?? 3000}`;
}
export const withTRPCConfig = withTRPC<AppRouter>({
config({ ctx }) {
return {
url: `${getBaseUrl()}/api/trpc`,
};
},
ssr: false,
});
</code>
<code>import { AppRouter } from '@/trpc';
import { withTRPC } from '@trpc/next';
function getBaseUrl() {
if (typeof window !== 'undefined') {
return '';
}
if (process.env.VERCEL_URL) {
return `https://${process.env.VERCEL_URL}`;
}
return `http://localhost:${process.env.PORT ?? 3000}`;
}
export const withTRPCConfig = withTRPC<AppRouter>({
config({ ctx }) {
return {
url: `${getBaseUrl()}/api/trpc`,
};
},
ssr: false,
});
</code>
import { AppRouter } from '@/trpc';
import { withTRPC } from '@trpc/next';
function getBaseUrl() {
if (typeof window !== 'undefined') {
return '';
}
if (process.env.VERCEL_URL) {
return `https://${process.env.VERCEL_URL}`;
}
return `http://localhost:${process.env.PORT ?? 3000}`;
}
export const withTRPCConfig = withTRPC<AppRouter>({
config({ ctx }) {
return {
url: `${getBaseUrl()}/api/trpc`,
};
},
ssr: false,
});
src/app/api/trpc/[trpc]/route.ts
:
<code>import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
import { appRouter } from '@/trpc';
const handler = (req: Request) =>
fetchRequestHandler({
endpoint: '/api/trpc',
req,
router: appRouter,
createContext: () => ({}),
});
export { handler as GET, handler as POST };
</code>
<code>import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
import { appRouter } from '@/trpc';
const handler = (req: Request) =>
fetchRequestHandler({
endpoint: '/api/trpc',
req,
router: appRouter,
createContext: () => ({}),
});
export { handler as GET, handler as POST };
</code>
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
import { appRouter } from '@/trpc';
const handler = (req: Request) =>
fetchRequestHandler({
endpoint: '/api/trpc',
req,
router: appRouter,
createContext: () => ({}),
});
export { handler as GET, handler as POST };
src/app/auth-callback/page.tsx
:
<code>"use client"
import { useRouter, useSearchParams } from "next/navigation"
import { trpc } from "../_trpc/client"
const Page = () => {
const router = useRouter()
const searchParams = useSearchParams()
const origin = searchParams.get('orogin')
const { data, isLoading, isError, isSuccess } = trpc.authCallback.useQuery();
if (isSuccess) {
router.push(origin ? `/${origin}` : '/dashboard')
}
}
export default Page
</code>
<code>"use client"
import { useRouter, useSearchParams } from "next/navigation"
import { trpc } from "../_trpc/client"
const Page = () => {
const router = useRouter()
const searchParams = useSearchParams()
const origin = searchParams.get('orogin')
const { data, isLoading, isError, isSuccess } = trpc.authCallback.useQuery();
if (isSuccess) {
router.push(origin ? `/${origin}` : '/dashboard')
}
}
export default Page
</code>
"use client"
import { useRouter, useSearchParams } from "next/navigation"
import { trpc } from "../_trpc/client"
const Page = () => {
const router = useRouter()
const searchParams = useSearchParams()
const origin = searchParams.get('orogin')
const { data, isLoading, isError, isSuccess } = trpc.authCallback.useQuery();
if (isSuccess) {
router.push(origin ? `/${origin}` : '/dashboard')
}
}
export default Page
src/trpc/index.ts
:
<code>import { getKindeServerSession } from '@kinde-oss/kinde-auth-nextjs/server';
import { publicProcedure, router } from './trpc';
import { TRPCError } from '@trpc/server';
export const appRouter = router({
authCallback: publicProcedure.query(async () => {
const { getUser } = getKindeServerSession();
const user = await getUser();
if (!user?.id || !user?.email)
throw new TRPCError({ code: 'UNAUTHORIZED' });
return { success: true };
}),
});
export type AppRouter = typeof appRouter;
</code>
<code>import { getKindeServerSession } from '@kinde-oss/kinde-auth-nextjs/server';
import { publicProcedure, router } from './trpc';
import { TRPCError } from '@trpc/server';
export const appRouter = router({
authCallback: publicProcedure.query(async () => {
const { getUser } = getKindeServerSession();
const user = await getUser();
if (!user?.id || !user?.email)
throw new TRPCError({ code: 'UNAUTHORIZED' });
return { success: true };
}),
});
export type AppRouter = typeof appRouter;
</code>
import { getKindeServerSession } from '@kinde-oss/kinde-auth-nextjs/server';
import { publicProcedure, router } from './trpc';
import { TRPCError } from '@trpc/server';
export const appRouter = router({
authCallback: publicProcedure.query(async () => {
const { getUser } = getKindeServerSession();
const user = await getUser();
if (!user?.id || !user?.email)
throw new TRPCError({ code: 'UNAUTHORIZED' });
return { success: true };
}),
});
export type AppRouter = typeof appRouter;
src/trpc/trpc.ts
:
<code>import { initTRPC } from '@trpc/server';
const t = initTRPC.create();
export const router = t.router;
export const publicProcedure = t.procedure;
</code>
<code>import { initTRPC } from '@trpc/server';
const t = initTRPC.create();
export const router = t.router;
export const publicProcedure = t.procedure;
</code>
import { initTRPC } from '@trpc/server';
const t = initTRPC.create();
export const router = t.router;
export const publicProcedure = t.procedure;
Additional Details:
- Next.js version: “14.2.3”
- React version: “^18”
- tRPC version: 11.0.0-rc.374
- @tanstack/react-query version: “^5.37.1”
What I’ve Tried:
- Checked the API route configuration and endpoint URLs.
- Verified the TRPC setup and procedure definitions.
Question:
Since I am using tRPC for the first time I don’t why am I encountering the Unable to find tRPC Context
error, Is there anything I’ve missed or misconfigured in the setup?
Any help or insights would be greatly appreciated!