PerpsError. An empty list from a data read means only one fact: the account exists and has no rows.
Status reads and data reads
A status read tells you what the user must do next:
- Lighter
getAccountreturns a zero fee tier andapiKeyRegistered: falsewhen the wallet has no locally stored API key that matches the registered key. Otherwise it reads the fee tier with the resolved token and throwsUnauthorizedif Lighter rejects the token.getAvailableToTradereads throughgetAccount, so it throws the sameUnauthorized. - Ondo
getAccountreturns an empty account without a session, and OndoaccountExistsreturnsfalse. - Ondo
getDepositFlowandgetWithdrawFlowreturnkind: 'setupRequired'without a session. - Hyperliquid
accountExistsreturnsfalsebefore the wallet’s first deposit, whilegetDepositFlowremains available.
getAccount throws in two cases:
AccountNotFoundfor a wallet with no Lighter account. CallaccountExistsbeforegetAccount.Unauthorizedwhen an auth token resolves for the registered API key and Lighter rejects the token on the fee-tier read.
Fact to code
Each data read throws one code per fact:Before and after a read
checkSetup() tells you before a read what the read will throw. The thrown code tells you after the read. Both report the same fact, with the Lighter token-ordering exception that follows the table. A UI can use one or both.
For a Lighter wallet with no account,
checkSetup() returns an empty setup list and an empty checklist, so it has no registerApiKey step to offer. Treat the missing account as the first fact: offer onboarding, also when a Lighter read throws SetupRequired.
checkSetup() cannot predict Unauthorized, because the venue decides it when it receives the credential. On Ondo, the provider removes the rejected session token, so the next checkSetup() shows siweLogin as unsatisfied.
checkSetup() is not a pure read. Call it once after each setup step, not before each data read. See checkSetup.
Per provider
Lighter
getOrders,getOrder,getFills,getActivityandgetPortfolioHistoryneed an auth token. They throwSetupRequiredwhen no token resolves,Unauthorizedwhen Lighter rejects the token, andAccountNotFoundwhen the wallet has no Lighter account.- These reads check the token before the account. A wallet with no Lighter account and no token gets
SetupRequired. - When Lighter reports an SDK-owned read-only token as revoked, the SDK replaces the token and retries the read once. If Lighter rejects the new token, the read throws
Unauthorized. getPositionsandgetWithdrawableBalancesneed no token. Their only access code isAccountNotFound.getAvailableToTradereads throughgetAccounton every Lighter market. It throwsAccountNotFoundfor a wallet with no Lighter account, andUnauthorizedwhen an auth token resolves for the registered API key and Lighter rejects the token.getMarketSettingsneeds no token. It returns the venue default for a wallet with no Lighter account.getOrderswithstatuses: []returns an empty list without a token. It sends no request to Lighter.- The WebSocket
orderUpdatesandpositionschannels throwSetupRequiredat subscribe time when no token resolves. When no auth-token resolver is wired, they throwSDKError— a wiring defect, not an account state, so no account setup fixes it. See Lighter WebSocket. orderUpdates,fills,positionsandaccountSummaryeach resolve the Lighter account index before the channel opens, so every one throwsAccountNotFoundat subscribe time for a wallet with no Lighter account — includingfillsandaccountSummary, which need no token.accountSummarydegrades to the publicaccount_allvariant instead of throwing when no token resolves.
Ondo
getPositions,getOrders,getOrder,getFills,getActivity,getPortfolioHistory,getWithdrawableBalances,getAvailableToTradeandgetMarketSettingsneed a session. They throwSetupRequiredwhen no session token is stored, and the provider sends no request to Ondo.- When Ondo rejects the stored session token, the provider removes the token and that read throws
Unauthorized. The next read throwsSetupRequired. - Ondo opens the account at the SIWE login, so an Ondo data read does not throw
AccountNotFound. getOrderswithstatuses: []also throwsSetupRequiredwithout a session.- The WebSocket account channels throw
SetupRequiredat subscribe time when no session is stored.
Hyperliquid
- Hyperliquid account reads need no credential, so they do not throw
SetupRequired. getAccount,getPositions,getOrders,getOrder,getFills,getActivity,getPortfolioHistory,getWithdrawableBalances,getAvailableToTradeandgetMarketSettingsfirst checkpreTransferCheck.userExists. They throwAccountNotFoundbefore reading account data when it isfalse.getOrderswithstatuses: []still performs the account check before returning an empty list.orderUpdates,fills,positions,spotBalances,accountSummaryandavailableToTradeWebSocket subscriptions throwAccountNotFoundbefore opening a venue channel.accountExistsremains a boolean status read, andgetDepositFlowremains available before account creation.- A Hyperliquid
/inforead that the venue rejects with HTTP 401 throwsUnauthorized.