Axios Plugin#
@kubb/plugin-axios generates a type-safe, per-operation async function for every OpenAPI operation, using Axios as the HTTP transport. It lives in the kubb-labs/plugins monorepo under packages/plugin-axios.
The plugin shares its option surface, resolver, and code-generation components with @kubb/plugin-fetch via a shared @internals/client package — only the template runtime differs. Consumer plugins (react-query, vue-query, swr, MCP) declare a dependency on plugin-axios by name and import the generated <op> functions rather than embedding their own HTTP client.
Entry Points#
| File | Purpose |
|---|---|
src/plugin.ts | Plugin factory (pluginAxios), hooks, file injection |
src/generators/clientGenerator.tsx | Per-operation generator — delegates to createClientGenerator<PluginAxios>('axios') |
src/templates.ts | Absolute paths to the three bundled template files |
templates/axios.ts | Full Axios runtime (types, createClientCore, resolveRequest, settleResponse) |
src/types.ts | PluginAxios factory type; re-exports Options / ResolvedOptions from @internals/client |
Template-Driven Code Generation#
During the kubb:plugin:setup hook the plugin injects three static files into the project's .kubb/ directory :
.kubb/client.ts— the full Axios runtime, copied verbatim fromtemplates/axios.ts. IfbaseURLis set, the plugin appendsclient.setConfig({ baseURL: ... })as a footer ..kubb/serializers.ts— query/body/path serializers fromtemplates/serializers.ts..kubb/standardSchema.ts— Standard Schema validation helper fromtemplates/standardSchema.ts.
Generated operation files import client and RequestConfig / ResponseErrorConfig from .kubb/client.ts. The only runtime dependency in generated code is axios itself.
The per-operation clientGenerator calls createClientGenerator<PluginAxios>('axios') from @internals/client, which emits one async function per OpenAPI operation wrapping a single grouped options object.
Request Resolution Logic#
The central function is resolveRequest inside templates/axios.ts. It runs before every Axios call and handles:
- Serialization — merges per-call and client-level serializers for query, body, and path; falls back to defaults .
- Auth — calls
resolveAuthwhich walks the per-operationsecurityarray and places the first resolved token in headers or query params. - Body — runs
validator.request(if set), then serializes via codec or body serializer; stripsContent-TypeforFormDataso Axios appends the multipart boundary . throwOnError/validateStatus— resolved at line 485–486 (see next section).- Final
AxiosRequestConfig— assembled at lines 490–503 and handed toactiveInstance.request(...).
After the call, settleResponse decodes the body through the matching codec and runs validator.response or validator.error.
Consumer plugins resolve which client plugin to call via resolveClient (in @internals/client), which auto-detects plugin-axios when it is the only registered contract client, or accepts an explicit client: 'axios' selector. resolveClientOperation then caches the resolved function name and file path per operation node.
validateStatus and throwOnError#
Both are first-class fields on RequestConfig and ClientConfig.
Resolution order :
throwOnError = requestConfig.throwOnError ?? config.throwOnError ?? true
validateStatus = requestConfig.validateStatus ?? config.validateStatus ?? (throwOnError ? undefined : () => true)
throwOnError: true(default) —validateStatusis left asundefined, so Axios uses its own default (throw on any non-2xx). When Axios throws,createClientCorecatches theAxiosErrorand re-throws it as aResponseError, a typed error class carryingdata,status,statusText,contentType,request, andresponse.throwOnError: false—validateStatusis forced to() => true, telling Axios to resolve for every status. The response is then handed tosettleResponse, which populateserrorinstead ofdatafor non-2xx responses. NoResponseErroris thrown; callers switch onresult.statusorresult.error.- A custom
validateStatusoverrides both: you control exactly which statuses Axios throws for, independently ofthrowOnError.
The RequestResult type reflects this at the TypeScript level: with ThrowOnError extends true, the return type narrows to only the 2xx SuccessResultUnion; with false, it expands to the full ResultUnion including error variants .
Client-level defaults are set via client.setConfig({ throwOnError, validateStatus }) ; per-call overrides go in the options argument of each generated function.
Plugin Options Reference#
Options are defined in @internals/client types and documented at docs.kubb.dev/kubb/plugins/plugin-client.
| Option | Default | Notes |
|---|---|---|
output.path | 'clients' | Output folder for generated files |
baseURL | — | Appended as client.setConfig(...) footer in .kubb/client.ts |
validator | false | 'zod' or { request?, response? } to validate via @kubb/plugin-zod |
sdk | — | Swap per-operation functions for a class-based SDK (`mode: 'tag' |
resolver | — | Override generated name and file-path conventions |
group | — | Group files by tag into sub-folders |
include / exclude / override | — | Filter or override options per tag, operationId, path, method, or content type |