Guides

Errors

Response envelope

When the server returns an error it sets a 4xx or 5xx status and sends a JSON body of the form:

{
  "code": "validation_error",
  "message": "Request validation failed.",
  "errors": [{ "path": "name", "message": "must not be empty" }]
}

Error codes

The code field is one of the following string literals:

CodeMeaning
validation_errorRequest body or query string failed schema validation
bad_requestMalformed request that is not a validation issue
unauthorizedNo credentials provided
api_key_missingAuthorization header present but no key value
api_key_invalidKey does not match any active key on the team
api_key_expiredKey has passed its expiry date
insufficient_scopeKey is valid but lacks the scope for this operation
forbiddenAuthenticated but not permitted
not_foundResource does not exist
conflictWrite conflicts with existing state (e.g. duplicate)
rate_limitedRequest rate exceeded
too_many_requestsBurst limit exceeded
not_implementedEndpoint exists in the schema but is not yet live
agent_limit_reachedTeam has reached its agent quota
internal_errorUnexpected server error

Error hierarchy

Every error the SDK throws extends BimpeAIError.

BimpeAIError
├── UserError
├── ConnectionError
│   └── ConnectionTimeoutError
└── ApiError
    ├── BadRequestError
    │   └── ValidationError
    ├── AuthenticationError
    ├── PermissionDeniedError
    ├── NotFoundError
    ├── ConflictError
    ├── RateLimitError
    ├── InternalServerError
    └── NotImplementedError

UserError is thrown before a request goes out — for example when you construct a client without an API key.

ConnectionError means no response was received. ConnectionTimeoutError extends it and is thrown when the per-request timeout elapses.

Every ApiError carries status, code, requestId, headers, and the raw body. code is an ErrorCode value or null when the server sent none.

ValidationError adds fieldErrors, an array of { path, message } objects.

RateLimitError adds retryAfter (seconds until the window resets), limit, remaining, and resetAt (a Date), read from the Retry-After and X-RateLimit-* response headers.

Every error raised by the SDK subclasses BimpeAIError.

BimpeAIError
├── UserError
├── APIConnectionError
│   └── APITimeoutError
└── APIError
    ├── BadRequestError
    │   └── ValidationError
    ├── AuthenticationError
    ├── PermissionDeniedError
    ├── NotFoundError
    ├── ConflictError
    ├── RateLimitError
    ├── InternalServerError
    └── APINotImplementedError

UserError is raised before a request goes out — for example when you construct a client with an empty API key.

APIConnectionError means no response was received. APITimeoutError extends it and is raised when the per-request timeout elapses.

Every APIError carries status, code, request_id, headers, and the raw body.

ValidationError adds field_errors, a list of {"path": ..., "message": ...} dicts.

RateLimitError adds retry_after (seconds), limit, remaining, and reset_at, read from the Retry-After and X-RateLimit-* response headers.

Handling errors

import { RateLimitError, ValidationError } from '@bimpeai/sdk';

try {
  await bimpe.agents.create({ name: '' });
} catch (error) {
  if (error instanceof ValidationError) {
    for (const field of error.fieldErrors) console.warn(`${field.path}: ${field.message}`);
  } else if (error instanceof RateLimitError) {
    console.warn(`retry in ${error.retryAfter}s`);
  } else {
    throw error;
  }
}
from bimpeai import RateLimitError, ValidationError

try:
    client.agents.create(name="")
except ValidationError as err:
    for field in err.field_errors:
        print(field["path"], field["message"])
except RateLimitError as err:
    print("retry after", err.retry_after, "seconds")

On this page