Skip to main content
PMXT’s error hierarchy is designed so the same except/catch clause works in both hosted and self-hosted modes. Hosted errors descend from HostedTradingError and from a semantic parent (InsufficientFunds, InvalidOrder, AuthenticationError, etc.). Self-hosted errors raise the semantic parent directly. Catch the parent and you cover both paths. For recovery patterns and the five most-common errors with code, see Handling hosted errors.

Hierarchy

PmxtError                                    (root for the whole SDK)
├── ValidationError                          (local-only — bad arguments)
│   └── MissingWalletAddress                 (escrow call without wallet_address)
├── AuthenticationError
│   ├── InvalidApiKey                  ◄── hosted
│   └── InvalidSignature               ◄── hosted
├── InsufficientFunds
│   └── InsufficientEscrowBalance      ◄── hosted
├── InvalidOrder
│   ├── OrderSizeTooSmall              ◄── hosted
│   ├── BuiltOrderExpired              ◄── hosted
│   └── NoLiquidity                    ◄── hosted
├── NotFoundError
│   └── OutcomeNotFound                ◄── hosted
├── ExchangeNotAvailable
│   └── CatalogUnavailable             ◄── hosted (retryable)
├── NotSupported
└── HostedTradingError                       (any 4xx/5xx from trade.pmxt.dev)

    └── (all classes marked ◄── hosted above are also HostedTradingError)
In Python this is implemented via multi-inheritance: class InsufficientEscrowBalance(InsufficientFunds, HostedTradingError). In TypeScript, JS single-inheritance means each hosted leaf extends only its semantic parent, and the HostedTradingError membership is carried by a static isHostedError = true flag. Use the isHostedError(e) helper to test for membership.

HostedTradingError

Root of all errors returned by trade.pmxt.dev.
Status codeAny 4xx or 5xx from the hosted trading API
Detail body{ "error": "..." } or { "detail": "..." } or { "success": false, "error": "..." }
Parents (Python)PmxtError
TS membershipe instanceof HostedTradingError or isHostedError(e) === true
Retryable5xx → yes; 4xx → no (unless a leaf overrides)
Fieldse.status (int), e.detail (str)
from pmxt._hosted_errors import HostedTradingError

try:
    client.create_order(...)
except HostedTradingError as e:
    print(e.status, e.detail)

InsufficientEscrowBalance

Escrow free balance is below the order’s USDC requirement.
Status code400
Detail starts withInsufficient escrow balance
Parents (Python)InsufficientFunds, HostedTradingError
TS extendsInsufficientFunds; static isHostedError = true
RetryableNo (deposit and retry)
Recovery: top up via client.escrow.deposit_tx(...).

OrderSizeTooSmall

Resolved share count is below the venue’s minimum (Polymarket: 5 shares).
Status code400
Detail containsbelow the minimum
Parents (Python)InvalidOrder, HostedTradingError
TS extendsInvalidOrder; static isHostedError = true
RetryableNo (resize and retry)

InvalidApiKey

pmxt_api_key is missing, malformed, revoked, or expired.
Status code401 (always)
Detailinvalid api key or missing api key
Parents (Python)AuthenticationError, HostedTradingError
TS extendsAuthenticationError; static isHostedError = true
RetryableNo
Recovery: rotate the key in the dashboard. Do not retry with the same key.

OutcomeNotFound

Catalog could not resolve the requested outcome_id (or market_id).
Status code404
Detail containscatalog: no outcome
Parents (Python)NotFoundError, HostedTradingError
TS extendsNotFoundError; static isHostedError = true
RetryableNo
Most often: you passed a venue-native ID to a hosted endpoint that expects a catalog UUID. See Catalog UUID vs venue ID.

CatalogUnavailable

The hosted catalog is temporarily unavailable.
Status code502 / 503
Detail starts withcatalog:
Parents (Python)ExchangeNotAvailable, HostedTradingError
TS extendsExchangeNotAvailable; static isHostedError = true
RetryableYes (override on DEFAULT_RETRYABLE)
Recovery: retry with exponential backoff.

BuiltOrderExpired

The built_order_id or cancel_id TTL elapsed before submit/cancel.
Status code400
Detail containsbuilt_order_id expired or cancel_id expired
Parents (Python)InvalidOrder, HostedTradingError
TS extendsInvalidOrder; static isHostedError = true
RetryableNo (re-build and re-sign)
Re-call build_order, re-sign, re-submit. Common cause: slow hardware-wallet confirmations.

InvalidSignature

The hosted trading API rejected the EIP-712 signature or typed-data shape.
Status code400 / 401
Detail containsInvalid signature
Parents (Python)AuthenticationError, HostedTradingError
TS extendsAuthenticationError; static isHostedError = true
RetryableNo
Most often: signing the wrong domain (chain ID, verifying contract). See Signing.

NoLiquidity

Empty book on the side you’re crossing.
Status code400
Detail containsbook has no resting asks or book has no resting bids
Parents (Python)InvalidOrder, HostedTradingError
TS extendsInvalidOrder; static isHostedError = true
RetryableNo (post a limit instead, or wait)

MissingWalletAddress

Local validation — client.escrow.* was called without a wallet_address.
Status coden/a (local)
Parents (Python)ValidationError
TS extendsValidationError
Hosted member?No — this is a local pre-flight check, not a hosted-API response
Pass wallet_address to the exchange constructor.

Catching by intent

IntentCatch (Python)Catch (TypeScript)
Any hosted errorexcept HostedTradingErrorif (isHostedError(e))
Any auth problemexcept AuthenticationErrore instanceof AuthenticationError
Any insufficient-fundsexcept InsufficientFundse instanceof InsufficientFunds
Any invalid orderexcept InvalidOrdere instanceof InvalidOrder
Anything PMXTexcept PmxtErrore instanceof PmxtError

See also