Error Handling in oRPC Clients
This guide explains how to handle type-safe errors in oRPC clients using type-safe error handling. Both server-side and client-side clients are supported.
Using safe
and isDefinedError
ts
import { isDefinedError, safe } from '@orpc/client'
const doSomething = os
.input(z.object({ id: z.string() }))
.errors({
RATE_LIMIT_EXCEEDED: {
data: z.object({ retryAfter: z.number() })
}
})
.handler(async ({ input, errors }) => {
throw errors.RATE_LIMIT_EXCEEDED({ data: { retryAfter: 1000 } })
return { id: input.id }
})
.callable()
const [error, data, isDefined] = await safe(doSomething({ id: '123' }))
// or const { error, data, isDefined } = await safe(doSomething({ id: '123' }))
if (isDefinedError(error)) { // or isDefined
// handle known error
console.log(error.data.retryAfter)
}
else if (error) {
// handle unknown error
}
else {
// handle success
console.log(data)
}
INFO
safe
works liketry/catch
, but can infer error types.safe
supports both tuple[error, data, isDefined]
and object{ error, data, isDefined }
styles.isDefinedError
checks if an error originates from.errors
.isDefined
can replaceisDefinedError
Safe Client
If you often use safe
for error handling, createSafeClient
can simplify your code by automatically wrapping all procedure calls with safe
. It works with both server-side and client-side clients.
ts
import { createSafeClient } from '@orpc/client'
const safeClient = createSafeClient(client)
const [error, data] = await safeClient.doSomething({ id: '123' })