Catch PolyesterError subclasses. Full tree: Errors reference.
from polyester import (
PolyesterError,
PolyesterTransportError,
PolyesterRateLimitError,
PolyesterValidationError,
PolyesterRealtimeOverflowError,
is_retryable_error,
mutation_outcome_unknown,
)
import asyncio
try:
await client.orders.create(
symbol="BTC-USDT",
side="buy",
order_type="limit",
tif="gtc",
qty="0.01",
price="60000",
client_order_id=client_order_id,
)
except PolyesterRealtimeOverflowError:
# Only relevant for subscriptions, resubscribe after catching up
...
except PolyesterRateLimitError as err:
await asyncio.sleep(err.retry_after or 1.0)
# reconcile this create by client_order_id before resubmitting
except PolyesterTransportError:
# outcome may be unknown; reconcile before resubmitting
...
except PolyesterValidationError as err:
# bad input / post_only misuse / encode failure, do not retry blindly
print(err)
except PolyesterError as err:
print(err)Retry rules
- Use
is_retryable_error(err)and capped exponential backoff. - If
mutation_outcome_unknown(err)is true, reconcile state before retrying. - For a single-order create, reconcile by the stable
client_order_idbefore resubmitting. Retained reuse returnsCONFLICT_DUPLICATE_CLIENT_ORDER_ID, not the earlier result. - Reuse replayable
request_idorclient_trigger_idvalues for the same logical action. - Withdrawals also reuse the same required idempotency key, nonce, and signed payload.
- Do not generate a fresh idempotency key inside the retry loop.
- Realtime overflow is fail-closed: treat it as fatal for that subscription.
The async client also applies cooperative backpressure if a burst exhausts the bounded
authentication timestamp window. This does not block the event loop. Direct users of the
synchronous polyester.auth.sign_request helper instead receive PolyesterRateLimitError immediately and should honor retry_after.
client_order_id can double-place an order if the first attempt already applied.
Keep the original ID for reconciliation; a duplicate conflict does not replay the earlier outcome.Cancellation and deadlines
Cancelling a task that awaits an SDK call raises asyncio.CancelledError in that task, and asyncio.timeout around the call raises TimeoutError. This holds for every API call, retried
reads included. Let CancelledError propagate; do not catch it as an SDK error. A canceled answer
from the server is still PolyesterServerError, and a call that runs past the client's own timeout still raises a PolyesterTransportError, usually PolyesterTimeoutError.
import asyncio
try:
async with asyncio.timeout(2.0):
open_orders = await client.orders.list_open()
except TimeoutError:
# your own deadline passed; reconcile a mutation cut short this way before resending it
...Validation & precision
PolyesterValidationError covers client-side encode failures (unknown enums, post_only on market,
IOC, or FOK orders, bad shapes). Catalog miss / excess precision usually surfaces here or as an API
error, there is no separate CatalogConversionError class in Python. A quantity whose scaled value
does not fit the signed 64-bit wire field, or a Decimal too large or too precise for its field,
raises PolyesterValidationError before anything is sent.
MFA / step-up
Interactive MFA step-up and session elevation are JWT/session product flows. API-key bots should
not expect to create keys or complete MFA challenges through this SDK. Helpers is_step_up_required / is_mfa_elevation_required exist for shared error codes if you integrate
with session products elsewhere.
Streaming errors
Unary methods raise. Subscriptions surface terminal errors via the async iterator / sub.error, including PolyesterRealtimeOverflowError. See Streaming.