Axios
Officialv5.5.11@kubb/plugin-axios
Handle errors
Handle failures from the client Kubb generates. Catch a ResponseError, switch to a returned error result with throwOnError, and tell a network failure apart from a 4xx or 5xx response.
The generated client throws a ResponseError on non-2xx responses by default:
import { getPetById } from './gen/clients/getPetById'
import { ResponseError } from './gen/.kubb/client'
try {
const { data } = await getPetById({ path: { petId: 1 } })
console.info(data.name)
} catch (error) {
if (ResponseError.is(error)) {
console.error(error.status) // 404
console.error(error.data) // the parsed error body
}
}The message holds the HTTP method and the URL without its query string, so query credentials stay out of logs. For example: GET https://api.example.com/pets/1 failed with status 404 Not Found.
The error exposes these fields:
class ResponseError extends Error {
static is(error: unknown): error is ResponseError<unknown, unknown, unknown>
data: TError // the parsed error body
status: number
statusText: string
contentType: string | undefined
request: AxiosRequestConfig
response: AxiosResponse
}Each generated package bundles its own ResponseError class, so narrow with ResponseError.is(error) instead of instanceof. is() checks the error name.
Return the error instead
Pass throwOnError: false and the call resolves for every documented status. The result is a
discriminated union: data is set on success and error on failure. Branch on status,
because an empty error body can leave error empty or undefined.
const result = await getPetById({ path: { petId: 1 }, throwOnError: false })
if (result.status === 200) {
console.info(result.data.name)
}
if (result.status !== 200) {
console.error(result.status, result.error)
}Set the generated default
Set throwOnErrorDefault on the client plugin to choose how generated operations handle non-2xx
responses by default. Each call can still override that setting with throwOnError:
import { pluginAxios } from '@kubb/plugin-axios'
pluginAxios({ throwOnErrorDefault: false })
// resolves with an error result
const list = await searchPets({ query: { status: 'available' } })
// opt one call back into throwing
const pet = await getPetById({ path: { petId: 1 }, throwOnError: true })client.setConfig({ throwOnError }) does not change this default, because each generated
operation passes its own value. Set it on the plugin.
Network failures still throw
throwOnError only applies when the server answers. A dropped connection, a DNS failure, or an
aborted AbortSignal always rejects. A ResponseError means the server answered with a non-2xx
status, and a ParseError means a body failed validation. Any other error usually means the
request never completed.try {
const { data } = await getPetById({ path: { petId: 1 }, throwOnError: false })
use(data)
} catch (error) {
// not a ResponseError: the request never completed
console.error('request failed to send', error)
}Pass an AbortSignal to cancel a request. The call rejects with the abort reason.
Validation failures
When you turn on the validator option, a body that does not match its Zod schema throws a
ParseError instead of returning. It carries the schema's raw issues:
import { ParseError } from './gen/.kubb/standardSchema'
try {
const { data } = await getPetById({ path: { petId: 1 } })
use(data)
} catch (error) {
if (error instanceof ParseError) {
console.error(error.issues) // [{ message, path }]
}
}A ParseError reports schema validation issues. A ResponseError reports a non-2xx status. With throwOnError: false, the error body is checked against its own error schema.
Calling .unwrap() on a throwOnError: false call turns that same error into a rejection, so a
try/catch works there too.