Errors

This page lists the error classes the SDK throws, the fields each carries, and the contract error names the SDK decodes into ContractRevertError. For the decision logic that goes with them, see Handle errors and reverts.

Every SDK error extends SomniaMarketsError, sets name to its class name, prefixes its message with @somnia-chain/markets-sdk: , and carries the underlying failure in cause when it wraps one.

Classes

All classes are exported from the root entry.

FillHistoryRestartRequiredError is returned by getUserFillsPage when a continuation belongs to a replaced serving dataset or is a legacy cursor without a generation. Its readonly cursorGeneration and servingGeneration fields identify the mismatch; legacy cursors report "legacy" as cursorGeneration. Discard accumulated pages and restart from page one; retrying the old cursor cannot succeed.

FillHistoryUnavailableError means the serving indexer has not initialized FillDataset/current. Deploy and reindex a compatible producer. Retrying the same deployment cannot make the contract appear.

ClassFieldsMeaningRetrying the same call
SomniaMarketsErrornoneBase class.depends on the subclass
InvalidInputErrorchainIds?: readonly number[]The call cannot proceed: unknown symbol or reference, unknown timeframe, a method used on the wrong market kind, an amount below one lot, a limit order without a price, a market order against an empty opposite side, a probability outside [0, 1], or a non-finite amount. Most cases are local validation. The empty-book market-order case follows a chain book read and depends on current liquidity. chainIds is set when a call names no chain on a multi-chain exchange (exchange.client, exchange.trader) and when createReactivity gets a wallet on another chain.fails again, except an empty-book market order may succeed after liquidity appears
NotConfiguredErrorwhat: stringThe client lacks a URL or address the feature needs: indexerUrl, wsRpcUrl, priceFeed, or an entry of addresses. Thrown at the first call that needs it, never at construction — a client built without an indexer still serves every chain-backed capability (smart accounts, executors, on-chain reads) and refuses indexer reads and live watches by feature.fails again
SignerRequiredErroroperation: stringAn authenticated method was called without a privateKey, account, walletClient, or executor. Authenticated methods include fetchBalance, fetchOpenOrders, fetchOrders, fetchMyTrades, fetchPositions, watchOrders, watchMyTrades, exchange.trader, and every write.fails again
CollateralOnWrongChainErrorchainId, code, needed, held, shortfall, elsewhere, plan?The order's collateral sits on another configured chainBridge the shortfall, then retry
BridgeLiquidityErrortoken, from, to, router, amount, availableA native bridge route (STT) pays out of the destination router's own balance, and that balance is below the amount. exchange.bridge.transfer, exchange.ensureFunds, and createOrder(…, { funding: "auto" }) read it first and send nothing.Retry after seeding, bridge at most available, or fund another way
BridgeDeliveryTimeoutErrormessageId, bridgeHash, from, to, token, amountexchange.ensureFunds or createOrder(…, { funding: "auto" }) sent the bridge leg, but the destination Mailbox did not process its message within the delivery timeout. The funds are in flight. exchange.bridge.transfer resolves with delivered: false and the same messageId instead of throwing.Call delivered(messageId) on the destination Mailbox before you bridge again
IndexerErroroperation: stringAn indexer request did not complete: endpoint down, bad URL, HTTP error, GraphQL error, or the 30-second request timeout. Never means "no such row".may succeed
IncompleteHistoryErroroperation, reason, pagesRead, maxFillPages?Portfolio analytics could not traverse all indexed fills: the caller's page budget ended or the cursor cycled. No partial PnL is returned.Increase or omit the budget; investigate a cursor cycle.
IndexerUnavailableErrorreason: IndexerRefusalReason, retryAfterMs: number, consecutiveFailures: numberThe SDK refused the read locally. reason says which gate refused: breaker-open (repeated endpoint failures — timeouts or HTTP 429/502/503/504 — opened the breaker), breaker-trial (the cooling period ended and another read is the trial), queue-full (this client already has maxQueued reads waiting), or live-reset (stopLive() reset live reads while it queued or backed off). For the first three, nothing reached the network; if a gate refuses a retry after an earlier attempt was sent, the read fails with that attempt's IndexerError instead. retryAfterMs is meaningful only for breaker-open and is 0 for the rest. A subclass of IndexerError, so existing instanceof IndexerError handling still catches it.Branch on reason: sleep retryAfterMs for breaker-open, retry shortly for breaker-trial, back off on your own schedule for queue-full, and retry live-reset on the same client
FillHistoryUnavailableErroroperation: stringThe serving indexer has no initialized fill-dataset generation.requires a compatible producer deployment and reindex
FillHistoryRestartRequiredErrorcursorGeneration: string, servingGeneration: stringA fill-page cursor belongs to a different serving generation or predates generation binding.requires a fresh first page without the old cursor
IndexerWaitTimeoutErrortargetBlock: number, latestProcessedBlock: number | null, timeoutMs: number, waitedMs: number, polls: numberThe indexer did not reach the requested block before the wait deadline. The fields report the target, last observed processed block (or null), deadline, elapsed time and metadata polls; unlike IndexerError, the indexer answered but remained behind.Retry with a longer deadline or handle the lag before reading.
RpcErroroperation: stringA JSON-RPC or WebSocket request did not complete: connection refused, 4-second request timeout, dropped subscription, unsupported method. From a write, it can also mean that the node refused the transaction (nonce too low, insufficient funds). Only the local-signer and session-key executors guarantee that nothing was sent otherwise; see Handle errors.a read may succeed; a write may succeed after you fix the refusal
TransactionOutcomeUnknownErrorchainId: number, operation: string, hash?A write signed a transaction that may have reached the node, and the SDK did not observe its receipt: the sync send timed out or its socket dropped, the receipt wait failed, or a session send lost its answer. The transaction can still mine. hash is absent only for a session send. A subclass of RpcError, so existing instanceof RpcError handling still catches it.do not retry blindly: look up hash (or read the state the write changes) first, because a retry can execute the write twice
ContractRevertErrorerrorName?, args?, reason?, data?, address?, functionName?The chain rejected the call. Thrown on send-time rejection, pre-send simulation, a mined receipt with failed status, and eth_call reads.fails again unless state changes
InvariantErrornoneThe SDK contradicted an invariant that its own control flow had established. It indicates an SDK defect, not invalid caller input.not applicable; report the SDK defect

Errors from code the SDK calls but does not own can surface unchanged. This includes a walletClient supplied by the app and the client returned by getViemClient(). Debug sink failures are different: the SDK contains them so diagnostic code cannot break an operation.

ContractRevertError fields

FieldTypePresent when
errorNamestringThe revert data matched a custom error in contractErrorsAbi.
argsreadonly unknown[]errorName is set. Positional decoded arguments.
reasonstringThe revert carried a require or revert string.
datastringThe node returned revert data.
addressstringThe reverting contract is known.
functionNamestringThe called function is known.

A mined transaction with status: "reverted" carries no revert data. The SDK replays the call as eth_call at the receipt's block to recover errorName or reason. When the replay yields nothing, the error is still a ContractRevertError and its message ends with (no revert data recoverable).

decodeRevert(caught) is exported for callers who send transactions themselves. It walks the cause chain, decodes the first revert data it finds against contractErrorsAbi, and always returns a ContractRevertError. It does not check that the input is a revert: a transport error passed to it returns a ContractRevertError without errorName.

Absence versus failure

OutcomeIndexer point read (get*)Indexer list read (list*)Chain readLive-store read
Row existsthe rowthe rowsthe valuethe value
No such rownull[]throws ContractRevertError or returns the contract's empty value[], null, or an empty book
Request failedthrows IndexerErrorthrows IndexerErrorthrows RpcError or ContractRevertErrornot applicable

Contract error names

contractErrorsAbi, exported from the root entry, is the generated ABI of every custom error the protocol contracts declare. ContractRevertError.errorName is one of its names. The names the exchange API and the trader raise most often:

AreaError names
Order validationInvalidPrice, InvalidQuantity, PriceNotAlignedToTickSize, QuantityNotAlignedToLotSize, QuantityBelowMinimum, PriceOutOfBounds, PriceTooLarge, TooManyRestingOrders
Market stateTradingNotActive, UseBinaryPlacement, MarketRestricted, MarketNotSettled, NotFinalized, StaleMarketId
Order lifecycleOrderDoesNotExist, IncorrectSender (a cancel of an order the caller does not own, including an order already cancelled), OrderAlreadyExpired, ExpiredOrderMustBeCancelled, NotExpired, OrderExpiryBeyondMarket
Time in forcePostOnlyWouldCross, FillOrKillNotFillable, ImmediateOrCancelNoFill, SelfMatchCancelTaker
Amend and batchAmendOldOrderGone, AmendReplacementRejected, EmptyOrderBatch, BatchTooLarge, LengthMismatch
FundsInsufficientBalance, InsufficientVaultBalance, ExceedsWithdrawableBalance, ERC20InsufficientAllowance, ERC20InsufficientBalance, InvalidMsgValue, NativeAmountMismatch
Builder feesBuilderNotApproved, BuilderFeeExceedsApproval, BuilderFeeExceedsCap, InvalidBuilder
Binary settlementNothingToClaim, AlreadyClaimed, NothingOwed, AlreadyFinalized, OracleNotAnswered, QuestionNotFinal
PerpsNoOpenPosition, InsufficientMargin, InsufficientMarginForOrder, InsufficientMarginAfterWithdrawal, MaxPositionSizeExceeded, OpenInterestCapExceeded, InvalidLeverage, MarkPriceUnavailable, OraclePriceStale, NotLiquidatable, PerpPoolNotRegistered
Stop ordersInvalidTriggerPrice, LimitPriceIncompatibleWithTrigger, InsufficientSomiPayment, TriggerTooCloseToEma, RefundFailed
Operators and venuesOperatorDisabled, OperatorNotActive, UnknownOperator, UnknownVenue, VenuePolicyDenied, InsufficientPermission, Unauthorized, NotOwner
Test collateralFaucetCapExceeded

The full list is longer and changes with the contracts. Read it from contractErrorsAbi in the installed version.