Customize Error Handling

Below is a structured guide on how to 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 will be raised.
  2. 4XX and 5XX Status Codes: Responses with these status codes are treated as errors.
  3. Connection Errors: If the SDK fails to connect to your server (DNS, timeouts, TLS errors), it raises a connection-related error/exception.
Example OpenAPI file
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 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

To improve the DX for the end user of the SDK, we recommend that you have named error classes for certain types of errors eg UnauthorizedError, NotFoundError, etc. It is also common that your API will return structured JSON errors for your 4XX responses. Here is an example of how you could configure this in your 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"
"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, we don’t tend to recommend defining 5XX responses as your server is not always in control of the response. If you do specify a JSON schema for a 5XX response and the response doesn’t match the schema, the SDK will raise a SDKValidationError.

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

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 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

Any unhandled API Error will raise a exception of the default SDKError/APIError/APIException class depending on the SDK language. To change the name of the default error class, edit the defaultErrorName parameter in your gen.yaml file for the corresponding SDK language:

python:
defaultErrorName: MyError

To rename other generated error classes, please refer to the Customizing Types documentation to rename generated error classes.

Handling the Default Error Response

The default response code is a catch-all for any status code not explicitly defined. By default, Speakeasy SDKs treat default responses as non-error responses. To treat it as a specific error type, define the 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 use the x-speakeasy-errors extension to override the default error-handling behavior of SDKs.

Apply 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. Merges with any parent x-speakeasy-errors extension unless override is true. Each status code must be in quotation marks (e.g., "503") for JSON and YAML compatibility. Wildcards (e.g., 5XX) are supported.

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

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

Another way to disable default error handling is to set the clientServerStatusCodesAsErrors option to false in your gen.yaml file for the SDK language:

go:
clientServerStatusCodesAsErrors: false