Skip to main content

Error Handling

The Conto SDK provides detailed error information to help you handle failures gracefully.

ContoError Class

SDK failures use the exported ContoError or ContoAdminError classes. They include stable error metadata alongside the standard Error fields:
Use error instanceof ContoError for agent-scoped calls and error instanceof ContoAdminError for organization-scoped calls. The structured fields are preserved from the API response when present.

Error Codes

Authentication Errors

Payment Errors

Validation Errors

System Errors

Handling Errors

Basic Error Handling

Handling Specific Error Codes

Enriched Denial And Error Responses

Some SDK responses include additional context to help agents recover programmatically. Policy denials from POST /api/sdk/payments/request are normal 200 responses with status: "DENIED", plus hint, context, and nextSteps fields. Execution failures are non-2xx error responses with an error and code.

Denial Response Structure

Example: Manual Execution Required

When trying to /execute a payment assigned to an external wallet:

Example: Policy Denial With Recovery Context

Handling Enriched Errors

Using Request and Execute for Better Control

The pay() method throws on denial. For more control, use separate request/execute:

Handling Rate Limits

The SDK handles rate limits during its built-in retry budget for safe requests (see Retry Strategy below). If those retries are exhausted, the thrown ContoError exposes retryAfter in seconds when the server supplied that guidance. Use that value to schedule a later retry only for a read or another operation that is safe to repeat:
Do not wrap payments.pay() or payments.execute() in a generic retry loop. If execution has an ambiguous failure, reconcile the known requestId with payments.status(requestId) before deciding whether another execution attempt is safe. Prefer separate request() and execute() calls, with a stable idempotencyKey, whenever the workflow needs deterministic recovery.

Handling Timeouts

For long-running requests, handle timeouts:

Retry Strategy

Built-in Automatic Retry

The SDK automatically retries transient failures only when repeating the request cannot create an additional side effect. Built-in behavior:
  • Retries read-only requests up to 3 times on network failures, 429, and 5xx
  • Retries payment authorization requests with the same stable idempotencyKey
  • Treats x402 and MPP pre-authorization as retryable, non-mutating policy checks
  • Respects Retry-After headers from the server
  • Exponential backoff: 1s → 2s → 4s (capped at 10s)
  • Never automatically retries payment execution, protocol record calls, or ContoAdmin mutations
  • Does not retry client errors (4xx except retryable 429 responses) or auth failures
For workflows that require deterministic recovery, prefer the separate request and execute methods over the pay convenience method so the application retains the requestId.

Custom Retry for Application Logic

For application-level retry logic (e.g., re-requesting after a denial), use a custom wrapper:

Logging Errors

Best Practices

Never let payment errors crash your application:
Don’t just catch generic errors:
Be careful with retries on payment execution:
Always log error details for debugging:

Next Steps

Examples

See complete integration examples

API Reference

View the REST API (Swagger UI)