Skip to main content

Error Handling

This guide covers error handling patterns when using the Paratro API and Go SDK.

Error Response Format

All API errors return a consistent JSON structure:
{
  "code": "not_found",
  "type": "not_found_error",
  "message": "Wallet not found"
}
FieldTypeDescription
codestringMachine-readable error code
typestringError category
messagestringHuman-readable description

Go SDK Error Handling

Quick Checks with Helper Functions

wallet, err := client.Wallet.GetWallet(ctx, walletID)
if err != nil {
    if paratro.IsNotFound(err) {
        // Handle 404
        log.Println("Wallet not found")
    } else if paratro.IsAuthError(err) {
        // Handle 401/403
        log.Println("Check your API credentials")
    } else if paratro.IsRateLimited(err) {
        // Handle 429
        log.Println("Rate limited, retry later")
    } else {
        log.Printf("Unexpected error: %v", err)
    }
    return
}

Detailed Error Inspection

Use errors.As to extract the full APIError and switch on specific error codes:
import "errors"

asset, err := client.Asset.CreateAsset(ctx, &paratro.CreateAssetRequest{
    AccountID: accountID,
    Symbol:    "USDT",
    Chain:     "ethereum",
})
if err != nil {
    var apiErr *paratro.APIError
    if errors.As(err, &apiErr) {
        switch apiErr.ErrorBody.Code {
        case "asset_already_exists":
            log.Println("Asset already added — skipping")
        case "account_not_active":
            log.Println("Account is not active")
        case "invalid_parameter":
            log.Printf("Invalid parameter: %s", apiErr.ErrorBody.Message)
        default:
            log.Printf("API error [%d]: %s - %s",
                apiErr.HTTPStatus, apiErr.ErrorBody.Code, apiErr.ErrorBody.Message)
        }
    } else {
        log.Printf("Network or client error: %v", err)
    }
    return
}

Rate Limit Retry Pattern

func createTransferWithRetry(ctx context.Context, client *paratro.MPCClient, req *paratro.CreateTransferRequest) (*paratro.TransferResponse, error) {
    maxRetries := 3
    for i := 0; i < maxRetries; i++ {
        result, err := client.Transaction.CreateTransfer(ctx, req)
        if err == nil {
            return result, nil
        }
        if paratro.IsRateLimited(err) && i < maxRetries-1 {
            time.Sleep(time.Duration(i+1) * time.Second)
            continue
        }
        return nil, err
    }
    return nil, fmt.Errorf("max retries exceeded")
}

Common Error Scenarios

CodeTypical CauseResolution
unauthorizedInvalid API credentialsVerify API Key and Secret
token_expiredJWT token expiredRequest a new JWT via /auth/token and retry the request
wallet_limit_reachedExceeded max wallet countContact support to increase limits
insufficient_balanceNot enough fundsCheck balance before transferring
invalid_addressWrong address format for chainEnsure address matches chain format
asset_already_existsToken already addedSkip or retrieve existing asset
too_many_requestsRate limit hitImplement backoff and retry