justindgmJ
tRPC3y ago
14 replies
justindgm

Vanilla Client Error Handling

What is the right way to handle errors when using the vanilla client?

If I setup a client like so:
import type { Router } from '../../../server/src/routers'

export const trpcClient = createTRPCProxyClient<Router>({
    links: [
        httpBatchLink({
            url: `${env.SERVER_URI}/trpc`
        })
    ]
})


And execute a mutation like so:
const user = await trpcClient.user.create.mutate({ email: string; password: string })


How should I handle errors? If I try to directly catch when calling the mutate function, the error is typed as
any

const user = await trpcClient.user.create.mutate({ email: string; password: string }).catch((error) => {
  // error is any
}


Is there a way to type narrow the error at runtime? On the server side, I am using the errorFormatter to add a custom field to my errors:
const t = initTRPC.context<Context>().create({
    isDev: env.NODE_ENV !== 'production',
    errorFormatter: ({ shape, error }) => {
        return {
            ...shape,
            data: {
                ...shape.data,
                customError: error.cause instanceof CustomError ? error.cause.customCode : null
            }
        }
    }
})


My current approach will be to use a runtime validation library like zod to check if this custom field exists on the error
const user = await trpcClient.user.create.mutate({ email: string; password: string }).catch((error) => {
  const parsedError = errorSchema.safeParse(error)
  if (parsedError.isSuccess) {
    console.error(parsedError.data.data.customError)
  } else {
    console.error(error)
  }
}


But this is clearly not ideal. Is this the right/best way to approach error handling with the vanilla client, or is there a better approach?
Solution
There is actually a docs page on this, does that answer the question? https://trpc.io/docs/client/vanilla/infer-types#infer-trpcclienterror-types
It is often useful to access the types of your API within your clients. For this purpose, you are able to infer the types contained in your AppRouter.
Inferring Types | tRPC
Was this page helpful?