Skip to Content
Symmio Frontier — the SDK surface for builders on HyperEVM

Errors

@symmio/trading-core uses one error class hierarchy for SDK-level failures and lets viem’s own errors pass through unwrapped. Two vocabularies — the SDK’s typed SymmError for configuration / HTTP / validation, and viem’s BaseError tree for on-chain and transport failures.

Class hierarchy

SymmError (all SDK-level failures — kind + code + message) └─ SymmApiError (HTTP failures — adds status, url, method, responseData)

SymmError

import { SymmError } from "@symmio/trading-core"; class SymmError extends Error { readonly name = "SymmError"; readonly kind: "config" | "api" | "validation"; readonly code: string; // e.g. "UNSUPPORTED_CHAIN" constructor(kind, code, message, options?); }
  • kind — broad classification for error-handling branches.
    • "config" — SDK configuration issues (missing chain, no wallet client).
    • "api" — REST / GraphQL / WebSocket transport failures.
    • "validation" — input validation (missing required parameter).
  • code — specific identifier within the kind ("UNSUPPORTED_CHAIN", "MISSING_USER").

SymmApiError extends SymmError

Every HTTP failure surfaces as SymmApiError with kind === "api":

class SymmApiError extends SymmError { readonly status: number; // HTTP status readonly statusText: string; readonly responseData: unknown; // raw response body (solver / hedger error payload) readonly url: string; readonly method: string; }

SymmApiError.fromAxios(err, { code, baseURL }) builds one from an axios error, preserving the original as cause and composing a single-line message: "<code>: <axios message> (<METHOD> <URL> → <status> <statusText>)".

Handling

import { SymmError, SymmApiError } from "@symmio/trading-core"; import { BaseError, ContractFunctionRevertedError, UserRejectedRequestError } from "viem"; try { await editAccountName(config, { account, name }); } catch (err) { if (err instanceof SymmApiError) { console.error(`HTTP ${err.status}`, err.responseData); return; } if (err instanceof SymmError) { if (err.kind === "config") console.error("Setup:", err.code, err.message); if (err.kind === "validation") console.error("Bad input:", err.code, err.message); return; } if (err instanceof BaseError) { const revert = err.walk((e) => e instanceof ContractFunctionRevertedError); if (revert instanceof ContractFunctionRevertedError) { console.log("revert reason:", revert.reason); return; } if (err.walk((e) => e instanceof UserRejectedRequestError)) return; } throw err; }

Alternatively check err.name === "SymmError" across realms.

Catalogue

Codes are stable strings. Group per kind. New codes may appear at any minor version; unknown code should fall through to a generic branch.

kind: "config"

CodeThrown byMeaning
NO_CHAINS_CONFIGUREDcreateConfigNo supported chains in the built-in registry.
UNSUPPORTED_CHAINConfig.getChainConfig, most reads/writesChain id not in the config registry.
NO_WALLET_CLIENTConfig.getWalletClient, every writecreateConfig was called without a getWalletClient resolver.
NO_WEBSOCKETConfig.getWebSocketConstructor, every streamNo webSocketConstructor and no globalThis.WebSocket.
PRICES_WS_NOT_CONFIGUREDwatchEnigmaPricesChain lacks a price-service WebSocket URL.
MUON_URLS_NOT_CONFIGUREDgetMuonRequestChain lacks Muon oracle URLs.

kind: "validation"

CodeThrown byMeaning
MISSING_USERgetUserSubAccounts, getUserSubAccountsAddresses, getSubAccountsCountOfUseruser parameter required.
MISSING_ACCOUNTSeveral read/write actionsaccount parameter required.
MISSING_OWNEROwnership-scoped readsowner parameter required.
MISSING_PARTY_AParty-A-scoped readspartyA parameter required.
MISSING_QUOTE_IDQuote-scoped readsquoteId parameter required.

kind: "api"

Selected — many more surface as SymmApiError with a _FAILED code per action:

CodeThrown by
FETCH_MARKETS_FAILEDgetMarkets
FETCH_LOCKED_PARAMS_FAILEDgetLockedParams
FETCH_NOTIONAL_CAP_FAILEDgetNotionalCap
FETCH_NOTIONAL_CAP_ALL_FAILEDgetNotionalCapAll
FETCH_SOLVER_ERROR_CODES_FAILEDgetSolverErrorCodes
FETCH_MUON_REQUEST_FAILEDgetMuonRequest
FETCH_ENIGMA_PRICE_SERVICE_HEALTH_FAILEDgetEnigmaPriceServiceHealth
FETCH_ENIGMA_PRICE_SERVICE_METADATA_FAILEDgetEnigmaPriceServiceMetadata
FETCH_ENIGMA_PRICE_SERVICE_PRICES_BY_NAMES_FAILEDgetEnigmaPriceServicePricesByNames
FETCH_ENIGMA_PRICE_SERVICE_PRICES_BY_ADDRESSES_FAILEDgetEnigmaPriceServicePricesByAddresses
FETCH_ENIGMA_PRICE_SERVICE_SYMBOLS_INFO_FAILEDgetEnigmaPriceServiceSymbolsInfo
GET_INSTANT_OPENS_FAILEDgetInstantOpens
GET_INSTANT_CLOSES_FAILEDgetInstantCloses
GET_INSTANT_OPEN_QUOTE_ID_FAILEDgetInstantOpenQuoteId
SEARCH_NOTIFICATIONS_FAILEDsearchNotifications
SET_TPSL_REJECTEDsetQuoteTpSl (handler returned failure)
DELETE_TPSL_REJECTEDdeleteQuoteTpSl (handler returned failure)
FETCH_QUOTE_TPSL_FAILEDgetQuoteTpSl
TPSL_SOCKET_ERRORwatchTpSlNotifications
NOTIFICATIONS_SOCKET_ERRORwatchNotifications
PRICES_SOCKET_ERRORwatchEnigmaPrices

viem errors (on-chain / transport)

Contract reverts, gas failures, wallet rejections, RPC unreachable — all bubble up as viem errors. Use BaseError.walk() to inspect the cause chain.

import { BaseError, ContractFunctionRevertedError } from "viem"; if (err instanceof BaseError) { const revert = err.walk((e) => e instanceof ContractFunctionRevertedError); if (revert) console.log(revert.reason); }

React

@symmio/trading-react normalizes both — every hook wraps queryFn / mutationFn and runs failures through normalizeSymmErrorSymmioRequestError (discriminated by kind). See the React errors page.

Last updated on