# 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](../how-to/handle-errors).

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](./fill-history-pages); retrying the old cursor cannot succeed. `getUserFillHistory` makes at most two attempts: its first read or refresh, then one full read when the first cannot stand. It throws this error when the dataset changes during that full read. Call it again.

`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.

`PerpPositionChangesUnavailableError` means the serving indexer predates the `PerpPositionChange` table, so `listPerpPositionChangesForFills` has no position updates to pair fills with. Show each fill's own side until the indexer is reindexed by a compatible producer. Retrying the same deployment cannot make the table appear.

| Class                                 | Fields                                                                                                                  | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | Retrying the same call                                                                                                                                                                    |
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SomniaMarketsError`                  | none                                                                                                                    | Base class.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | depends on the subclass                                                                                                                                                                   |
| `InvalidInputError`                   | `chainIds?: 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                                                                                                        |
| `NotConfiguredError`                  | `what: string`                                                                                                          | The 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                                                                                                                                                                               |
| `NotSupportedError`                   | `feature: string`                                                                                                       | The call is valid, but this SDK version does not support it yet, for example the `"spot"` and `"overall"` scopes of `getAccountEquity`. Thrown before any network request.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | fails again                                                                                                                                                                               |
| `SignerRequiredError`                 | `operation: string`                                                                                                     | An 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                                                                                                                                                                               |
| `CollateralOnWrongChainError`         | `chainId`, `code`, `needed`, `held`, `shortfall`, `elsewhere`, `plan?`                                                  | The order's collateral sits on another configured chain                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | Bridge the shortfall, then retry                                                                                                                                                          |
| `BridgeLiquidityError`                | `token`, `from`, `to`, `router`, `amount`, `available`                                                                  | A 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                                                                                                                      |
| `BridgeDeliveryTimeoutError`          | `messageId`, `bridgeHash`, `from`, `to`, `token`, `amount`                                                              | `exchange.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                                                                                                            |
| `BridgeDeliveryUnknownError`          | `messageId`, `bridgeHash`, `from`, `to`, `token`, `amount`, `operation`                                                 | `exchange.bridge.transfer`, `exchange.ensureFunds` or `createOrder(…, { funding: "auto" })` sent the bridge leg, and its origin transaction was mined, but the wait for delivery failed. `operation` is `watch bridge delivery` when the destination watch failed or the delivery holds no payout from the router, and `waitForTransactionReceipt` when the read of the delivery receipt failed. The funds may be in flight. `ensureFunds` keeps the leg pending, as on a timeout. A subclass of `RpcError`, so existing `instanceof RpcError` handling still catches it.                                                                                                                                                                                  | Call `delivered(messageId)` on the destination Mailbox before you bridge again                                                                                                            |
| `IndexerError`                        | `operation: string`                                                                                                     | An 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                                                                                                                                                                               |
| `IncompleteHistoryError`              | `operation`, `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.                                                                                                                                  |
| `IncompletePortfolioError`            | `account`, `limit`, `nextOffset`                                                                                        | `getClaimable` observed more nonzero positions than its complete-read budget. No incomplete claim array is returned.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Use `getClaimablePage` and follow its raw-position `nextOffset`.                                                                                                                          |
| `IndexerUnavailableError`             | `reason: IndexerRefusalReason`, `retryAfterMs: number`, `consecutiveFailures: number`                                   | The 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 |
| `AccountViewError`                    | `reason: AccountViewErrorReason`, `chainId: number`, `operation: string`                                                | An account-view read (`client.accountOrders`, `client.accountOutcomePositions`) got an answer the SDK cannot accept as one complete account. `invalidResponse`: the data breaks the account-view contract. `scopeMismatch`: the data belongs to another account, chain or dataset. `snapshotUnstable`: the account changed during every read attempt. It never means an empty account. A subclass of `IndexerError`, so existing `instanceof IndexerError` handling still catches it.                                                                                                                                                                                                                                                                      | `snapshotUnstable` can succeed at once. The other two succeed only after the indexer serves correct data                                                                                  |
| `FillHistoryUnavailableError`         | `operation: string`                                                                                                     | The serving indexer has no initialized fill-dataset generation.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | requires a compatible producer deployment and reindex                                                                                                                                     |
| `PerpPositionChangesUnavailableError` | `operation: string`                                                                                                     | The serving indexer predates the `PerpPositionChange` table, so fills cannot be paired with their position updates.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | fails the same way until a compatible producer reindexes the indexer                                                                                                                      |
| `FillHistoryRestartRequiredError`     | `cursorGeneration: string`, `servingGeneration: string`                                                                 | A fill-page cursor belongs to a different serving generation or predates generation binding.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | requires a fresh first page without the old cursor                                                                                                                                        |
| `AccountsIndexerUnavailableError`     | `operation: string`, `retryAfterMs: number \| undefined`, `chainId?: number`                                            | A smart-account indexed read (`client.accounts.*`, `exchange.accounts.*`) found the accounts indexer rate-limited, overloaded or unreachable. `retryAfterMs` is how long it asked to wait, when it said. A subclass of `IndexerError`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Wait `retryAfterMs` (or back off) and retry                                                                                                                                               |
| `AccountFeedRestartRequiredError`     | `chainId: number`                                                                                                       | A smart-account feed cursor (`getActivityPage`, `getAccountsPage`, `getNetworkActivityPage`, `getFactoryHistoryPage`) was issued before that chain's accounts index was rebuilt; continuing would skip or repeat rows.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Discard the pages read; start the read again without a cursor                                                                                                                             |
| `IndexerWaitTimeoutError`             | `targetBlock: number`, `latestProcessedBlock: number \| null`, `timeoutMs: number`, `waitedMs: number`, `polls: number` | The 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.                                                                                                                            |
| `RpcError`                            | `operation: string`                                                                                                     | A 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](../how-to/handle-errors).                                                                                                                                                                                                                                                                                                                                                            | a read may succeed; a write may succeed after you fix the refusal                                                                                                                         |
| `TransactionOutcomeUnknownError`      | `chainId: 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                                                             |
| `ContractRevertError`                 | `errorName?`, `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                                                                                                                                                          |
| `InvariantError`                      | none                                                                                                                    | The 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

| Field          | Type                 | Present when                                                   |
| -------------- | -------------------- | -------------------------------------------------------------- |
| `errorName`    | `string`             | The revert data matched a custom error in `contractErrorsAbi`. |
| `args`         | `readonly unknown[]` | `errorName` is set. Positional decoded arguments.              |
| `reason`       | `string`             | The revert carried a `require` or `revert` string.             |
| `data`         | `string`             | The node returned revert data.                                 |
| `address`      | `string`             | The reverting contract is known.                               |
| `functionName` | `string`             | The 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

| Outcome        | Indexer point read (`get*`) | Indexer list read (`list*`) | Chain read                                                         | Live-store read                |
| -------------- | --------------------------- | --------------------------- | ------------------------------------------------------------------ | ------------------------------ |
| Row exists     | the row                     | the rows                    | the value                                                          | the value                      |
| No such row    | `null`                      | `[]`                        | throws `ContractRevertError` or returns the contract's empty value | `[]`, `null`, or an empty book |
| Request failed | throws `IndexerError`       | throws `IndexerError`       | throws `RpcError` or `ContractRevertError`                         | not 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:

| Area                 | Error names                                                                                                                                                                                                                                                                |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Order validation     | `InvalidPrice`, `InvalidQuantity`, `PriceNotAlignedToTickSize`, `QuantityNotAlignedToLotSize`, `QuantityBelowMinimum`, `PriceOutOfBounds`, `PriceTooLarge`, `TooManyRestingOrders`                                                                                         |
| Market state         | `TradingNotActive`, `UseBinaryPlacement`, `MarketRestricted`, `MarketNotSettled`, `NotFinalized`, `StaleMarketId`                                                                                                                                                          |
| Order lifecycle      | `OrderDoesNotExist`, `IncorrectSender` (a cancel of an order the caller does not own, including an order already cancelled), `OrderAlreadyExpired`, `ExpiredOrderMustBeCancelled`, `NotExpired`, `OrderExpiryBeyondMarket`                                                 |
| Time in force        | `PostOnlyWouldCross`, `FillOrKillNotFillable`, `ImmediateOrCancelNoFill`, `SelfMatchCancelTaker`                                                                                                                                                                           |
| Amend and batch      | `AmendOldOrderGone`, `AmendReplacementRejected`, `EmptyOrderBatch`, `BatchTooLarge`, `LengthMismatch`                                                                                                                                                                      |
| Funds                | `InsufficientBalance`, `InsufficientVaultBalance`, `ExceedsWithdrawableBalance`, `ERC20InsufficientAllowance`, `ERC20InsufficientBalance`, `InvalidMsgValue`, `NativeAmountMismatch`                                                                                       |
| Builder fees         | `BuilderNotApproved`, `BuilderFeeExceedsApproval`, `BuilderFeeExceedsCap`, `InvalidBuilder`                                                                                                                                                                                |
| Binary settlement    | `NothingToClaim`, `AlreadyClaimed`, `NothingOwed`, `AlreadyFinalized`, `OracleNotAnswered`, `QuestionNotFinal`                                                                                                                                                             |
| Perps                | `NoOpenPosition`, `InsufficientMargin`, `InsufficientMarginForOrder`, `InsufficientMarginAfterWithdrawal`, `MaxPositionSizeExceeded`, `OpenInterestCapExceeded`, `InvalidLeverage`, `MarkPriceUnavailable`, `OraclePriceStale`, `NotLiquidatable`, `PerpPoolNotRegistered` |
| Stop orders          | `InvalidTriggerPrice`, `LimitPriceIncompatibleWithTrigger`, `InsufficientSomiPayment`, `TriggerTooCloseToEma`, `RefundFailed`                                                                                                                                              |
| Operators and venues | `OperatorDisabled`, `OperatorNotActive`, `UnknownOperator`, `UnknownVenue`, `VenuePolicyDenied`, `InsufficientPermission`, `Unauthorized`, `NotOwner`                                                                                                                      |
| Test collateral      | `FaucetCapExceeded`                                                                                                                                                                                                                                                        |

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

---

Every page is also Markdown: append `.md` to its URL, or ask for `text/markdown`. Found something wrong, missing or confusing in these docs? Tell us: `POST /api/feedback` on this site with JSON `{"message": "…", "context": "what you were doing and what happened", "page": "…"}`, or a plain-text body. `GET /api/feedback` gives the JSON Schema. The team reads every one.
