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

ContoError

SDK failures use the exported ContoError class. It exposes only stable customer-facing metadata:
For validation failures, fieldErrors identifies recognized request fields with locally generated guidance. The pay() helper preserves allowlisted customer-facing denial reasons. The SDK does not forward arbitrary server details, workflow instructions, or provider diagnostics.

Error Codes

Authentication Errors

Payment Errors

A repeated execute call after completion can return 400 INVALID_STATUS; a concurrent execution can return 409 ALREADY_EXECUTED. Both require reading the original request, not sending again. Do not rely on a single HTTP status to identify an earlier successful execution.

Validation Errors

System Errors

For the full state transition and recovery flow, see Track and recover a payment.

Handling Errors

Basic Error Handling

Handling Specific Error Codes

Decision And Error Boundaries

Policy denials from payments.request() are normal decision responses with status: "DENIED". Transport, authentication, validation, and execution failures throw ContoError. Use separate request and execute calls when your application needs to handle those outcomes independently. The pay() method throws on denial. For more control, use separate request/execute:

Handling Rate Limits

The SDK handles retryable rate limits before throwing (see Retry Strategy). If the request is still rate limited, ContoError.retryAfter may provide a server-supplied delay in seconds. Otherwise, back off on your own schedule. If you need an additional application-level retry after the SDK has exhausted its own, wrap the call and back off on your own schedule:

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:
Log the stable fields needed to investigate a failed request. Do not log request bodies, credentials, arbitrary response objects, or payment context:

Next Steps

Examples

See complete integration examples

API Reference

View the REST API (Swagger UI)