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:
| Code | Meaning |
|---|---|
validation_error | Request body or query string failed schema validation |
bad_request | Malformed request that is not a validation issue |
unauthorized | No credentials provided |
api_key_missing | Authorization header present but no key value |
api_key_invalid | Key does not match any active key on the team |
api_key_expired | Key has passed its expiry date |
insufficient_scope | Key is valid but lacks the scope for this operation |
forbidden | Authenticated but not permitted |
not_found | Resource does not exist |
conflict | Write conflicts with existing state (e.g. duplicate) |
rate_limited | Request rate exceeded |
too_many_requests | Burst limit exceeded |
not_implemented | Endpoint exists in the schema but is not yet live |
agent_limit_reached | Team has reached its agent quota |
internal_error | Unexpected server error |
Error hierarchy
Every error the SDK throws extends BimpeAIError.
BimpeAIError
├── UserError
├── ConnectionError
│ └── ConnectionTimeoutError
└── ApiError
├── BadRequestError
│ └── ValidationError
├── AuthenticationError
├── PermissionDeniedError
├── NotFoundError
├── ConflictError
├── RateLimitError
├── InternalServerError
└── NotImplementedErrorUserError 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
└── APINotImplementedErrorUserError 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")