create-t3-app: bug: Recent Commit Breaks Clerk Based Authentication w/ tRPC

Provide environment information

“initVersion”: “7.23.2”

System: OS: Linux 5.15 Ubuntu 20.04.6 LTS (Focal Fossa) CPU: (16) x64 Intel® Core™ i7-10700 CPU @ 2.90GHz Memory: 9.02 GB / 15.58 GB Container: Yes Shell: 5.8 - /usr/bin/zsh Binaries: Node: 18.18.0 - ~/.nvm/versions/node/v18.18.0/bin/node Yarn: 1.22.17 - ~/.yarn/bin/yarn npm: 10.1.0 - ~/.nvm/versions/node/v18.18.0/bin/npm pnpm: 8.9.2 - ~/.local/share/pnpm/pnpm bun: 1.0.7 - ~/.bun/bin/bun

Describe the bug

I’ve encountered an issue with the recent changes introduced in commit e6649f18963086b2d016815e60cc9915711a85d8. These changes appear to have broken the Clerk based authentication, which in turn is affecting the functionality of tRPC in my application.

Reproduction repo

https://github.com/Jacksonmills/gpts-browser

To reproduce

To reproduce, revert the changes back to main in this commit e6649f18963086b2d016815e60cc9915711a85d8. Once reverted, log in with Clerk and visit a page with a query to get:

Unhandled Runtime Error
Error: Cannot read properties of undefined (reading 'resolve')

image

Additional information

I was able to revert the changes in the problematic commit, which fixes all my issues. However, I would love if someone could further explain or suggest how we can go back to using cookies while also making Clerk work. That would be ideal! Thank you. 👏

About this issue

  • Original URL
  • State: closed
  • Created 8 months ago
  • Reactions: 3
  • Comments: 18 (8 by maintainers)

Most upvoted comments

@bhatvikrant Use the auth function instead of getAuth() which will not require the req parameter

https://clerk.com/docs/references/nextjs/auth#auth

image

“initVersion”: “7.24.1”

Ik this issue is closed but I am facing the following error:

Cannot read properties of undefined (reading 'headers') 

I am using clerk with the latest version of T3, App router.

Contents of my trpc.ts file are:

/**
 * YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
 * 1. You want to modify request context (see Part 1).
 * 2. You want to create a new middleware or type of procedure (see Part 3).
 *
 * TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
 * need to use are documented accordingly near the end.
 */
import { SignedInAuthObject, SignedOutAuthObject, getAuth } from "@clerk/nextjs/server";
import { TRPCError, initTRPC } from "@trpc/server";
import superjson from "superjson";
import { ZodError } from "zod";
import * as trpcNext from '@trpc/server/adapters/next';

import { db } from "~/server/db";

/**
 * 1. CONTEXT
 *
 * This section defines the "contexts" that are available in the backend API.
 *
 * These allow you to access things when processing a request, like the database, the session, etc.
 *
 * This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
 * wrap this and provides the required context.
 *
 * @see https://trpc.io/docs/server/context
 */
interface AuthContext {
  auth: SignedInAuthObject | SignedOutAuthObject;
}
 
export const createContextInner = async ({ auth }: AuthContext  ) => {
  return {
    db,
    auth
  }
}


export const createTRPCContext = async (opts: trpcNext.CreateNextContextOptions) => {
  // return {
  //   db,
  //   ...opts,
  // };

  return await createContextInner({ auth: getAuth(opts.req) })
};

/**
 * 2. INITIALIZATION
 *
 * This is where the tRPC API is initialized, connecting the context and transformer. We also parse
 * ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
 * errors on the backend.
 */
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,
      },
    };
  },
});

/**
 * 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
 *
 * These are the pieces you use to build your tRPC API. You should import these a lot in the
 * "/src/server/api/routers" directory.
 */

/**
 * This is how you create new routers and sub-routers in your tRPC API.
 *
 * @see https://trpc.io/docs/router
 */
export const createTRPCRouter = t.router;

/**
 * Public (unauthenticated) procedure
 *
 * This is the base piece you use to build new queries and mutations on your tRPC API. It does not
 * guarantee that a user querying is authorized, but you can still access user session data if they
 * are logged in.
 */
export const publicProcedure = t.procedure;


// check if the user is signed in, otherwise throw a UNAUTHORIZED CODE
const isAuthed = t.middleware(({ next, ctx }) => {
  if (!ctx.auth.userId) {
    throw new TRPCError({ code: 'UNAUTHORIZED', message: 'User is not logged in, from middleware.' })
  }
  return next({
    ctx: {
      auth: ctx.auth,
    },
  })
})

export const protectedProcedure = t.procedure.use(isAuthed)

as soon as I make this change I start getting errors in src/trpc/server.ts and src/app/api/trpc/[trpc]/route.ts

src/trpc/server.ts file src/trpc/server.ts file

src/trpc/server.ts error src/trpc/server.ts error

src/app/api/trpc/[trpc]/route.ts file src/app/api/trpc/[trpc]/route.ts file

src/app/api/trpc/[trpc]/route.ts error src/app/api/trpc/[trpc]/route.ts error

Not sure what is wrong here, I followed the clerk docs for integrating with trpc

@juliusmarminge @JacobMGEvans @Jacksonmills

clerk is still broken + unuseable with next app router + trpc – unreal that this has been getting 0 attention in the community

Hey @eula01, which community are you referring to? In Clerk we are addressing this tRPC issue and @royanger is working on definitive workarounds. If there is something in particular we haven’t addressed or you have additional concerns, please let us know.

@Jacksonmills I appreciate you bringing this up here and in Clerk, we will be collaborating with Julius and potentially tRPC members as well if necessary to find the right pattern/workaround, and then find the best path forward from there for a more permanent solution.

clerk is still broken + unuseable with next app router + trpc – unreal that this has been getting 0 attention in the community

same problem here. Had to make the reversion mentioned above.

I had the same issue because Clerk was not happy that the user agent was missing after transitioning from headers to cookies only. I fixed it for now by including the bearer token in server.ts.

import { cookies } from "next/headers"
import { auth } from "@clerk/nextjs"
import {
  createTRPCProxyClient,
  loggerLink,
  unstable_httpBatchStreamLink,
} from "@trpc/client"
import { type AppRouter } from "~/server/api/root"

import { getUrl, transformer } from "./shared"

export const api = createTRPCProxyClient<AppRouter>({
  transformer,
  links: [
    loggerLink({
      enabled: (op) =>
        process.env.NODE_ENV === "development" ||
        (op.direction === "down" && op.result instanceof Error),
    }),
    unstable_httpBatchStreamLink({
      url: getUrl(),
      async headers() {
        return {
          cookie: cookies().toString(),
          "x-trpc-source": "rsc",
          Authorization: `Bearer ${await auth().getToken()}`,
        }
      },
    }),
  ],
})

@imopbuilder thank you for this note ^ It was super helpful! 🙌

Nice @Arechii this worked for me, much easier than fully reverting the previous commit. I wonder… is this a potential long term fix? Also don’t forget to add to your server.ts asw as react.tsx

@t3dotgg please be aware of this when shilling clerk – unuseable DX  – clerk is fundamentally broken + incompatible with trpc & app router – and clerk devs have been radio silent for >2 months – 100s and 100s of comments and discussions on clerk discord and nothing!

Does anyone have a good working version of a simple server/api/trpc.ts which incorporates clerk? most of the docs floating around have not kept up with a myriad of changes, and I am still trying to wrap my head around combining numerous items into inner/outer context. TIA.

Hitting the same issue.

In the meantime if you just revert the changes from the linked commit Clerk will work fine

Hitting the same issue.