Skip to content

Error Handling

All errors thrown by the SDK extend a single base type, so you can catch any SDK error in one place or branch on the specific subclass when you need to react differently. The hierarchy is identical across the TypeScript and Python SDKs.

Error hierarchy

Error
└── ImbraceError (base — catch-all for SDK errors)
├── AuthError (401, 403 — invalid or expired credentials)
├── ApiError (4xx/5xx — request rejected by the server)
└── NetworkError (timeout, connection refused, DNS failure)

For specific error messages and known fixes, see Troubleshooting.


AuthError

Raised when the server returns 401 or 403 — credentials are invalid, expired, or revoked.

import { AuthError } from "@imbrace/sdk";
try {
const me = await client.platform.getMe();
} catch (e) {
if (e instanceof AuthError) {
console.error("Re-authenticate:", e.message);
}
}

ApiError

Raised for all other 4xx and 5xx responses (after retries are exhausted for 429/5xx).

import { ApiError } from "@imbrace/sdk";
try {
await client.marketplace.getProduct("nonexistent_id");
} catch (e) {
if (e instanceof ApiError) {
console.error(`HTTP ${e.statusCode}: ${e.message}`);
// e.g. "HTTP 404: Product not found"
}
}
PropertyTypeDescription
statusCodenumberHTTP status code
messagestringError message from server response

NetworkError

Raised when the request never reaches the server — timeout, DNS failure, or connection reset.

import { NetworkError } from "@imbrace/sdk";
try {
await client.platform.getMe();
} catch (e) {
if (e instanceof NetworkError) {
console.error("Cannot reach baseUrl:", e.message);
// e.g. "Request timed out after 30000ms"
}
}

Catching all SDK errors

Import the base type to handle any SDK-originated error in a single block:

import {
ImbraceClient,
ImbraceError,
AuthError,
ApiError,
NetworkError,
} from "@imbrace/sdk";
try {
await client.platform.getMe();
} catch (e) {
if (e instanceof AuthError) return handleAuthError(e);
if (e instanceof ApiError) return handleApiError(e);
if (e instanceof NetworkError) return handleNetworkError(e);
if (e instanceof ImbraceError) return handleUnknown(e);
throw e; // re-throw non-SDK errors
}

Automatic retry behavior

The HTTP transport in both SDKs retries transient failures with exponential backoff. The retry count differs slightly between languages but the conditions are identical.

ConditionAction
HTTP 429 (rate limit)Retry up to 2 times
HTTP 5xx (server error)Retry up to 2 times
Network error / timeoutRetry up to 2 times
HTTP 401 / 403No retry — throw AuthError immediately
HTTP 4xx (other)No retry — throw ApiError immediately

Backoff: 2^retryCount seconds between attempts (2s → 4s). Total worst-case: 3 attempts.


Request cancellation (TypeScript)

Pass an AbortSignal to cancel an in-flight request:

const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
try {
const result = await client.marketplace.listProducts(
{ page: 1 },
{ signal: controller.signal },
);
} catch (e) {
if (e instanceof NetworkError && e.message.includes("aborted")) {
console.log("Request cancelled");
}
}

Async error handling (Python)

The async client raises identical exception types:

from imbrace import AsyncImbraceClient, AuthError, ApiError
async with AsyncImbraceClient() as client:
try:
me = await client.platform.get_me()
except AuthError:
print("Re-authenticate")
except ApiError as e:
print(f"[{e.status_code}] {e}")

Best practices

// 1. Always handle AuthError separately — credentials need to be refreshed
// 2. Log ApiError.statusCode — 400 = bad params, 404 = not found, 409 = conflict
// 3. Wrap top-level entry points in try/catch
// 4. Don't retry on AuthError — won't help until credentials are fixed
async function safeGetMe(client: ImbraceClient) {
try {
return await client.platform.getMe();
} catch (e) {
if (e instanceof AuthError) {
await refreshCredentials();
return await client.platform.getMe();
}
throw e;
}
}