Errors
Every failure throws a typed error chosen by HTTP status, carrying the API's error code and request id.
Every API error throws. The class is chosen by HTTP status; the machine-readable code rides along for finer dispatch.
import { NotFoundError, RateLimitError } from '@ellipsis-dev/sdk';
try {
const { session } = await client.sessions.get('session_missing');
} catch (error) {
if (error instanceof NotFoundError) {
console.log(error.code, error.requestId);
} else if (error instanceof RateLimitError) {
// retries were already exhausted
} else {
throw error;
}
}The hierarchy
Error
└── EllipsisError
├── TransportError the request never got a response (DNS, TLS, timeout)
└── APIError a non-2xx response
├── AuthenticationError 401 token missing, invalid, or revoked
├── ForbiddenError 403 authenticated, not allowed
├── NotFoundError 404 no such resource in this account
├── ConflictError 409 conflicts with current state
├── UnprocessableError 422 request shape failed validation
├── RateLimitError 429 slow down
└── ServerError 5xx an error on our sideCheck instanceof EllipsisError to catch everything this SDK throws, or instanceof APIError for anything the API answered. Read .status when you care about a code the hierarchy does not name.
What an APIError carries
| Property | Value |
|---|---|
status | The HTTP status. |
code | The API's stable error code, or null when the response carried no envelope. |
message | The human-readable message, also the Error message. |
requestId | The id to quote in a support request, or null. |
body | The parsed response body, typed unknown. |
Switch on code, never on message text. The codes are an open vocabulary: new ones appear without a version break, so treat an unrecognized code by its status.
import { APIError } from '@ellipsis-dev/sdk';
try {
await handle.send('keep going');
} catch (error) {
if (error instanceof APIError && error.code === 'session_finished') {
handle = await client.sessions.run({ prompt: 'keep going' });
} else {
throw error;
}
}Retries happen first
429, 502, 503, and 504 are retried automatically with backoff before any error reaches you, maxRetries times. A RateLimitError in your code therefore means the retries were already exhausted. Transport failures are retried the same way, so a TransportError means the request never landed after every attempt.
Errors are not typed on the method
TypeScript has no checked exceptions, so a method's signature says nothing about what it throws. The list above is the whole surface: anything else escaping the client is a bug worth reporting.