Customize error handling

This structured guide demonstrates how you can configure and customize error handling in Speakeasy-generated SDKs.

Default error handling (no configuration)

By default, Speakeasy SDKs handle errors as follows:

  1. Validation errors: If the server response doesn’t match the SDK’s expected data schema, validation errors are raised.
  2. 4XX and 5XX status codes: If a server response includes these status codes, it is treated as an error.
  3. Connection errors: If the SDK fails to connect to your server (DNS, timeouts, TLS errors), a connection-related error or exception is raised.
Example OpenAPI document
openapi: 3.1.0
info:
title: The Speakeasy Bar
version: 1.0.0
servers:
- url: https://speakeasy.bar
paths:
/drinks:
get:
operationId: listDrinks
summary: Get a list of drinks
responses:
"200":
description: A list of drinks
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Drink"
components:
schemas:
Drink:
type: object
title: Drink
properties:
name:
type: string
TypeScript SDK default error handling
import { Drinks } from "drinks";
import {
SDKValidationError,
SDKError,
HTTPClientError,
} from "drinks/models/errors/index.js";
const drinks = new Drinks();
async function run() {
let result;
try {
result = await drinks.listDrinks();
console.log(result);
} catch (err) {
// 1. Validation errors: Server response didn't match the SDK's expected data schema
if (err instanceof SDKValidationError) {
// Raw value will be type `unknown`
console.error(err.rawValue);
// Validation errors can be pretty-printed
console.error(err.pretty());
return;
}
// 2. 4XX and 5XX status codes: Server returned an error code with an unexpected content type
// Use `typescript.defaultErrorName` to change the name of `SDKError` in `gen.yaml`
if (err instanceof SDKError) {
console.error(err.statusCode);
console.error(err.rawResponse.body);
return;
}
// 3. Connection errors: The SDK didn't even get a response from the server
if (err instanceof HTTPClientError) {
console.error(err.name);
console.error(err.message);
}
throw err;
}
}

Recommended configuration

We recommend that you configure custom names, such as UnauthorizedError or NotFoundError, for certain error classes to improve the developer experience for the end user of your SDK. For example, given that APIs commonly return structured JSON errors for 4XX status codes, you could name 4XX errors by defining their responses in your OpenAPI document as follows:

openapi: 3.1.0
info:
title: The Speakeasy Bar
version: 1.0.0
servers:
- url: https://speakeasy.bar
paths:
/drinks:
get:
operationId: listDrinks
summary: Get a list of drinks
responses:
"200":
description: A list of drinks
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Drink"
"401":
content:
application/json:
schema:
$ref: "#/components/schemas/UnauthorizedError"
"403":
content:
application/json:
schema:
$ref: "#/components/schemas/ForbiddenError"
"404":
content:
application/json:
schema:
$ref: "#/components/schemas/NotFoundError"
"429":
content:
application/json:
schema:
$ref: "#/components/schemas/TooManyRequestsError"
components:
schemas:
Drink:
type: object
title: Drink
properties:
name:
type: string
UnauthorizedError:
type: object
title: UnauthorizedError
properties:
message:
type: string
x-speakeasy-error-message: true
ForbiddenError:
type: object
title: ForbiddenError
properties:
message:
type: string
x-speakeasy-error-message: true
NotFoundError:
type: object
title: NotFoundError
properties:
message:
type: string
x-speakeasy-error-message: true
TooManyRequestsError:
type: object
title: TooManyRequestsError
properties:
message:
type: string
x-speakeasy-error-message: true

Note that we use x-speakeasy-error-message: true to configure the error message used by the SDK, which will be propagated to err.message in the SDK.

We don’t recommend defining 5XX responses in this way, as your server is not always in control of these responses. If you do specify a JSON schema for a 5XX response, and the response doesn’t match the schema, the SDK will raise an SDKValidationError.

TypeScript SDK default error handling
import { Drinks } from "drinks";
import {
SDKValidationError,
SDKError,
HTTPClientError,
UnauthorizedError,
ForbiddenError,
NotFoundError,
TooManyRequestsError,
} from "drinks/models/errors/index.js";
const drinks = new Drinks();
async function run() {
let result;
try {
result = await drinks.listDrinks();
console.log(result);
} catch (err) {
// Unauthorized
if (err instanceof UnauthorizedError) {
console.error(err.message);
return;
}
// Forbidden
if (err instanceof ForbiddenError) {
console.error(err.message);
return;
}
// Not found
if (err instanceof NotFoundError) {
console.error(err.message);
return;
}
// Too many requests
if (err instanceof TooManyRequestsError) {
console.error(err.message);
return;
}
// 1. Validation errors: Server response didn't match the SDK's expected data schema
if (err instanceof SDKValidationError) {
// Raw value will be type `string`
console.error(err.rawValue);
// Validation errors can be pretty-printed
console.error(err.pretty());
return;
}
// 2. 4XX and 5XX status codes: Server returned an error code with an unexpected content type
// Use `typescript.defaultErrorName` to change the name of `SDKError` in `gen.yaml`
if (err instanceof SDKError) {
console.error(err.statusCode);
console.error(err.rawResponse.body);
return;
}
// 3. Connection errors: The SDK didn't even get a response from the server
if (err instanceof HTTPClientError) {
console.error(err.name);
console.error(err.message);
}
throw err;
}
}

Advanced configuration

Renaming generated error classes

Unhandled API errors raise an exception of the default SDKError, APIError, or APIException class (depending on the SDK language). You can change the name of the default error class by editing the defaultErrorName parameter in your gen.yaml file for the corresponding SDK language:

python:
defaultErrorName: MyError

To rename other generated error classes, please consult the Customizing types documentation.

Handling the default error response

The default response code is a catch-all for any status code that is not explicitly defined. Speakeasy SDKs automatically treat default responses as non-error responses. To treat them as a specific error type, define a new default response in the x-speakeasy-errors extension on any operation:

x-speakeasy-errors:
statusCodes:
- "default"

Disabling default error handling

In certain cases, you may want to disable the default error-handling behavior of SDKs. For example, you may not want to throw an error for a 404 status code.

You can override this default behavior by adding the x-speakeasy-errors extension at the paths, path item, or operation level. Deeper levels merge or override parent behavior.

The x-speakeasy-errors extension is an object with the following properties:

PropertyTypeDescription
overridebooleanIf true, the statusCodes list overrides any parent x-speakeasy-errors extension for this object and its children. Defaults to false.
statusCodes[string]An array of status codes to handle as errors. It merges with any parent x-speakeasy-errors extension unless override is true. Each status code must be in quotation marks (for example, "503") for JSON and YAML compatibility. Wildcards (like 5XX) are supported.

If the statusCodes array contains undocumented status codes, the SDK returns an SDK error object containing the status code, the response body as a string, and the raw response object. Otherwise, if the content-type is application/json, it returns an error object from the response object in the OpenAPI document.

For example:

paths:
x-speakeasy-errors:
statusCodes: # Defines status codes to handle as errors for all operations
- 4XX # Wildcard to handle all status codes in the 400-499 range
- 5XX
/drinks:
x-speakeasy-errors:
override: true # Forces this path and its operations to only handle 404 and 500 as errors, overriding the parent x-speakeasy-errors extension at the paths level
statusCodes:
- 404
- 500
get:
x-speakeasy-errors:
statusCodes: # As override is not set to true, this operation will handle 404, 401, 500, and 503 as errors, merging with the parent x-speakeasy-errors extension at the path item level
- 401
- 503
operationId: getDrinks
responses:
200:
description: OK
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Drink"
401:
description: Unauthorized
content:
application/json: # As an application/json response is defined, the schema will generate a custom error object (for example `AuthError`) that will be returned and can be tested for
schema:
$ref: "#/components/schemas/AuthError"
404:
description: Not Found # As no application/json response is defined, the SDK will return a standard SDK error object.
500:
description: Internal Server Error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
503:
description: Service Unavailable

Alternatively, you can disable default error handling by setting the clientServerStatusCodesAsErrors option to false in your gen.yaml file for the relevant SDK language:

go:
clientServerStatusCodesAsErrors: false