Error Handling
The Tenzro Platform SDK provides typed errors for all failure cases, making it easy to handle errors gracefully in your application.
Error Types
All SDK errors extend the base TenzroError class:
import {
TenzroError,
AuthenticationError,
AuthorizationError,
ValidationError,
NotFoundError,
RateLimitError,
InternalError,
NetworkError,
} from '@tenzro/platform';Error Hierarchy
| Error Class | HTTP Status | Description |
|---|---|---|
AuthenticationError | 401 | Invalid or missing API key |
AuthorizationError | 403 | Insufficient permissions |
ValidationError | 400 | Invalid request parameters |
NotFoundError | 404 | Resource not found |
RateLimitError | 429 | Rate limit exceeded |
InternalError | 500+ | Server-side error |
NetworkError | - | Connection failed |
Basic Error Handling
try {
const wallet = await platform.wallet.create({
name: 'Treasury',
type: 'multi-sig',
chain: 'ethereum',
});
} catch (error) {
if (error instanceof TenzroError) {
console.error('API Error:', error.message);
console.error('Error Code:', error.code);
console.error('Request ID:', error.requestId);
} else {
throw error;
}
}Handling Specific Errors
import {
TenzroError,
AuthenticationError,
RateLimitError,
ValidationError,
} from '@tenzro/platform';
try {
await platform.wallet.create({ ... });
} catch (error) {
if (error instanceof AuthenticationError) {
// Invalid API key - check configuration
console.error('Authentication failed:', error.message);
// Redirect to auth or refresh token
} else if (error instanceof RateLimitError) {
// Rate limited - wait and retry
console.log(`Rate limited. Retry after ${error.retryAfter}s`);
await sleep(error.retryAfter * 1000);
// Retry the request
} else if (error instanceof ValidationError) {
// Invalid request - check parameters
console.error('Validation errors:', error.errors);
// error.errors is an array of field-level errors
for (const fieldError of error.errors) {
console.error(` ${fieldError.field}: ${fieldError.message}`);
}
} else if (error instanceof TenzroError) {
// Other API error
console.error('API error:', error.code, error.message);
} else {
throw error;
}
}Error Properties
All TenzroError instances have these properties:
interface TenzroError extends Error {
// Standard error message
message: string;
// Machine-readable error code
code: string;
// HTTP status code
status: number;
// Unique request identifier for support
requestId: string;
// Original response (if available)
response?: Response;
// Retry information (for rate limits)
retryAfter?: number;
// Field-level validation errors
errors?: Array<{
field: string;
message: string;
code: string;
}>;
}Validation Errors
ValidationError includes detailed field-level errors:
try {
await platform.wallet.create({
name: '', // Invalid: empty name
type: 'invalid-type', // Invalid: unknown type
chain: 'ethereum',
});
} catch (error) {
if (error instanceof ValidationError) {
// error.errors contains:
// [
// { field: 'name', message: 'Name is required', code: 'required' },
// { field: 'type', message: 'Invalid wallet type', code: 'invalid_enum' }
// ]
for (const err of error.errors) {
console.error(`${err.field}: ${err.message}`);
}
}
}Rate Limiting
Handle rate limits with exponential backoff:
async function withRetry<T>(
fn: () => Promise<T>,
maxRetries = 3
): Promise<T> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (error instanceof RateLimitError && attempt < maxRetries - 1) {
const delay = error.retryAfter
? error.retryAfter * 1000
: Math.pow(2, attempt) * 1000;
console.log(`Rate limited, retrying in ${delay}ms...`);
await new Promise(r => setTimeout(r, delay));
continue;
}
throw error;
}
}
throw new Error('Max retries exceeded');
}
// Usage
const wallet = await withRetry(() =>
platform.wallet.create({ name: 'Treasury', type: 'eoa', chain: 'ethereum' })
);Network Errors
Handle connection failures separately:
import { NetworkError } from '@tenzro/platform';
try {
await platform.wallet.list();
} catch (error) {
if (error instanceof NetworkError) {
console.error('Connection failed:', error.message);
console.error('Is offline?', !navigator.onLine);
// Show offline UI or retry later
}
}Global Error Handler
Set up a global error handler for consistent error processing:
import { TenzroError, RateLimitError } from '@tenzro/platform';
function handleTenzroError(error: unknown): never {
if (error instanceof RateLimitError) {
// Log and potentially queue for retry
logger.warn('Rate limited', {
requestId: error.requestId,
retryAfter: error.retryAfter,
});
} else if (error instanceof TenzroError) {
// Log API errors
logger.error('Tenzro API error', {
code: error.code,
message: error.message,
requestId: error.requestId,
status: error.status,
});
}
throw error;
}
// Usage with wrapper
async function safeApiCall<T>(fn: () => Promise<T>): Promise<T> {
try {
return await fn();
} catch (error) {
handleTenzroError(error);
}
}