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
safeworks liketry/catch, but can infer error types.safesupports both tuple[error, data, isDefined]and object{ error, data, isDefined }styles.isDefinedErrorchecks if an error originates from.errors.isDefinedcan 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' })