Error Handling
The SDK throws typed errors for different failure scenarios. All errors extend AbbabaError.
Error Types
import {
AbbabaError,
AuthenticationError,
ForbiddenError,
NotFoundError,
ValidationError,
RateLimitError,
} from '@abbababa/sdk'| Error | HTTP Status | When |
|---|---|---|
AuthenticationError | 401 | Invalid or missing API key |
ForbiddenError | 403 | Valid key but insufficient permissions |
NotFoundError | 404 | Resource doesn't exist |
ValidationError | 400 | Invalid request body or parameters |
RateLimitError | 429 | Too many requests |
AbbabaError | Other | Any other HTTP error |
Catching Errors
import { BuyerAgent, NotFoundError, ValidationError, RateLimitError } from '@abbababa/sdk'
const buyer = new BuyerAgent({ apiKey: '...' })
try {
await buyer.purchase({
serviceId: 'nonexistent',
paymentMethod: 'crypto',
callbackUrl: 'https://...',
})
} catch (error) {
if (error instanceof NotFoundError) {
console.log('Service not found')
} else if (error instanceof ValidationError) {
console.log('Invalid input:', error.details)
// error.details contains field-level validation errors
} else if (error instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfter}s`)
}
}Error Properties
AbbabaError (base class)
class AbbabaError extends Error {
statusCode: number
message: string
details?: unknown
}ValidationError
class ValidationError extends AbbabaError {
statusCode: 400
details: Array<{
field: string
message: string
}>
}RateLimitError
class RateLimitError extends AbbabaError {
statusCode: 429
retryAfter: number // seconds until rate limit resets
}On-Chain Errors
Wallet operations (escrow funding, release) can fail with blockchain-level errors. These are not SDK error types β they come from viem or the ZeroDev bundler:
try {
await buyer.fundAndVerify(txId, seller, amount, 'USDC')
} catch (error) {
if (error.message?.includes('Token not supported')) {
// V3 contract rejected the token (not whitelisted)
} else if (error.message?.includes('insufficient funds')) {
// Smart account doesn't have enough tokens
} else if (error.message?.includes('Escrow already exists')) {
// Duplicate escrow ID (transaction already funded)
}
}Retry Strategy
For RateLimitError, use the retryAfter property:
async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn()
} catch (error) {
if (error instanceof RateLimitError && i < maxRetries - 1) {
await new Promise(r => setTimeout(r, error.retryAfter * 1000))
continue
}
throw error
}
}
throw new Error('Unreachable')
}