Skip to content
NoetherDocs

Errors

Gateway HTTP error bodies, how failed transactions surface contract and host errors, and the error code tables of the deployed contracts.

Every error you can hit while integrating with Noether, in one place: the HTTP errors the gateway returns, how failed on-chain transactions surface in API responses, and the complete error code tables for the market, Trader Vault and referral contracts as deployed on testnet. Search this page by error name or code.

All examples are against the live gateway at https://noether-api.proudmeadow-533cf0d8.germanywestcentral.azurecontainerapps.io.

Gateway HTTP errors

The gateway returns JSON error bodies with a machine-readable error field. Summary first, exact bodies below.

Statuserror valueWhereMeaning
400FST_ERR_VALIDATIONAny endpointRequest params or body failed schema validation
400unsupported_assetPOST /v1/orders/prepareAsset symbol is not in the supported list
400simulation_failedPOST /v1/orders/prepareSoroban simulation rejected the operation before signing
400submission_rejectedPOST /v1/tx/submitThe RPC rejected the transaction at submission
401missing_bearerAuthenticated endpointsNo or non-Bearer Authorization header
401malformed_bearerAuthenticated endpointsBearer value missing the colon separator
401missing_timestampAuthenticated endpointsRequired X-Timestamp header absent
401stale_timestampAuthenticated endpointsX-Timestamp more than 30 seconds from server time
401invalid_credentialsAuthenticated endpointsUnknown or revoked key, or wrong secret
401invalid_signaturePOST /v1/keysBad, expired or reused challenge; wrong signature; fee-bump transaction; wrong operation
403not_in_betaPOST /v1/keysWallet address is not on the closed-beta allowlist
404(Fastify default)Unknown routeNo such path
404Unknown assetGET /v1/markets/{asset}, GET /v1/markets/{asset}/priceAsset not supported
404vault_not_foundGET /v1/vaults/{id}No Trader Vault with that id
404unknown_codeGET /v1/referral/lookupReferral code does not resolve
404no_codeGET /v1/referral/infoAddress never registered a referral code
404key_not_foundDELETE /v1/keys/{keyId}Key does not exist, belongs to someone else, or is already revoked
409key_limit_reachedPOST /v1/keysThe wallet already holds the maximum number of active keys
429rate_limitedAny endpoint except /v1/health and /docsRate limit exceeded for your tier
451region_restricted/v1/orders*, /v1/tx* onlyTrading blocked in your jurisdiction (configuration-dependent)
502rpc_errorPOST /v1/orders/prepare, POST /v1/tx/submitSoroban RPC unreachable or transport failure
503try_again_laterPOST /v1/tx/submitRPC transaction queue is full; resubmit shortly

400: validation and preparation failures

Schema validation failures carry the Fastify validation code in error, a human-readable message, and a validation array with the failing schema paths. Example (invalid candle interval):

{
  "error": "FST_ERR_VALIDATION",
  "message": "querystring/interval must be equal to one of the allowed values",
  "validation": [
    {
      "instancePath": "/interval",
      "schemaPath": "#/properties/interval/enum",
      "keyword": "enum",
      "params": { "allowedValues": ["1m", "5m", "15m", "1h", "4h", "1d", "1w"] },
      "message": "must be equal to one of the allowed values"
    }
  ]
}

Body validation runs before authentication, so a malformed POST /v1/orders/prepare body gets this 400 even without a key. POST /v1/orders/prepare adds two errors of its own:

{"error": "unsupported_asset", "asset": "XYZ"}
{"error": "simulation_failed", "message": "..."}

A simulation_failed at prepare time usually means the trade would revert on chain: insufficient collateral, a halted market, a contract error. Read the message; it often contains the underlying contract error. See how on-chain errors surface below.

401: authentication failures

Authenticated endpoints expect Authorization: Bearer <keyId>:<secret> and X-Timestamp (unix seconds) in every request. See Authentication for the full scheme. The failure bodies, in the order the gateway checks them:

{"error": "missing_bearer"}
{"error": "malformed_bearer", "hint": "use Bearer <keyId>:<secret>"}
{"error": "missing_timestamp"}
{"error": "stale_timestamp"}
{"error": "invalid_credentials"}

stale_timestamp means the X-Timestamp value drifted more than 30 seconds from server time. Key issuance (POST /v1/keys) has its own 401:

{"error": "invalid_signature"}

Causes: the challenge expired (five-minute TTL), was already used, the signature does not verify against the claimed address, the transaction is a fee-bump, or the first operation is not a manageData op carrying the challenge bytes. Challenges are held in gateway process memory, so a gateway restart voids outstanding challenges; request a fresh one and retry.

403: closed beta

API key issuance is gated to early-access wallets. A non-allowlisted address gets:

{
  "error": "not_in_beta",
  "message": "API key issuance is currently restricted to early-access wallets. Join the waitlist at noether.exchange to request access."
}

The gate applies at key issuance only. Public endpoints stay public, and a key you already hold keeps working. Check the gating state without auth via GET /v1/keys/beta-status.

404: not found

Unknown routes return Fastify's default:

{"message": "Route GET:/v1/nope not found", "error": "Not Found", "statusCode": 404}

Resource-specific 404 bodies:

{"error": "Unknown asset", "asset": "FOO"}
{"error": "vault_not_found", "id": 999}
{"error": "unknown_code", "code": "NOSUCHCODE"}
{"error": "no_code", "address": "GCHAX2N74WJVZLATV7WETVWZRHM5RSOINGELOHP2BRXTEC7AHUXUHHIT"}
{"error": "key_not_found"}

Note the asymmetry: GET /v1/markets/{asset} and GET /v1/markets/{asset}/price return 404 for unknown assets, but GET /v1/candles does not; it returns 200 with an empty candles array and source: "binance" instead.

409: key limit reached

POST /v1/keys refuses to mint another key when the wallet already holds the maximum number of active keys. The message states the count and the limit; revoke an unused key and retry.

{"error": "key_limit_reached", "message": "This wallet already has N active API keys (limit N). Revoke an unused key before issuing another."}

429: rate limited

Limits are per fixed 60-second window aligned to the wall-clock minute: 60 requests per minute unauthenticated (per IP), 600 requests per minute with a standard API key (per owning wallet). Every rate-limited response carries X-RateLimit-Tier and X-RateLimit-Remaining headers; /v1/health and /docs are exempt. Sending a valid key and X-Timestamp on any endpoint, even a public one, moves you to your wallet's higher bucket.

On breach you get a Retry-After header (seconds until the window resets) and:

{"error": "rate_limited", "retry_after_sec": 37}

Back off until retry_after_sec elapses, then resume.

451: region restricted

The trading endpoints (/v1/orders* and /v1/tx*) can be geo-restricted. When the restriction applies you get HTTP 451:

{
  "error": "region_restricted",
  "message": "Trading is not available in your jurisdiction. See the Terms of Service (restricted persons)."
}

This response is configuration-dependent: treat it as a possible response on the trading endpoints and handle it terminally (do not retry). Read-only endpoints, authentication and /v1/health are outside the geo-guarded surface.

5xx: upstream failures

{"error": "rpc_error", "message": "Upstream RPC request failed."}

HTTP 502: the gateway could not complete its Soroban RPC call. The body is deliberately opaque; the full error is in the gateway's logs under the x-request-id of your response. Retry with backoff. On POST /v1/tx/submit the body also carries "retryable": true.

{
  "error": "try_again_later",
  "retryable": true,
  "hash": "...",
  "message": "RPC transaction queue is full — resubmit the same signed XDR shortly"
}

HTTP 503, with Retry-After: 2: the RPC transaction queue is full. Resubmit the same signed XDR after the delay. POST /v1/tx/submit is idempotent, so resubmitting is safe and returns the prior result if the transaction already landed.

How on-chain errors surface

Noether contracts fail with typed Soroban contract errors; on the wire they look like Error(Contract, #22). The gateway decodes these for you at two points in the trading flow.

At prepare time. POST /v1/orders/prepare simulates the transaction before returning the unsigned XDR. If the contract would revert, you get 400 simulation_failed and never need to sign anything.

At submit time. POST /v1/tx/submit decodes the transaction's diagnostic events into a structured contractError object, and a hostError object when the Soroban host aborted outside contract code:

{
  "hash": "85895449a4...",
  "status": "FAILED",
  "contractError": {"code": 22, "name": "InsufficientCollateral"},
  "hostError": null,
  "txResultCode": "txFailed",
  "resultXdr": "AAAA..."
}

A transaction rejected before inclusion returns 400 submission_rejected with the same contractError, hostError and txResultCode fields. contractError is null when the failure is not a contract error; in that case look at hostError (for example {"type": "budget", "code": "exceeded_limit"} for a resource overrun, or a storage trap when the ledger state moved between simulation and apply, which a fresh prepare fixes) and txResultCode.

Two things to know when decoding:

  • The gateway maps the code number to a name from its own copy of the NoetherError table below. A code it does not recognize decodes as "UnknownContractError" with the raw number preserved, so match on code, not name.
  • Each contract has its own code space. NoetherError covers the market contract (and the shared vault, oracle shim and router errors). Trader Vault (FactoryError) and referral (ReferralError) codes overlap numerically with the low NoetherError codes; disambiguate by which contract your transaction invoked.

Most common while integrating

  • #30 PriceStale: the on-chain oracle price for the asset is older than 60 seconds and you are on a risk-increasing path (opens, entry-order checks). Closes and liquidations are never blocked by staleness. Trades sent through the app go through the Noether Router, which relays a fresh signed price in the same transaction; API-prepared transactions call the market directly, so retry after the keeper's next price push.
  • #22 InsufficientCollateral: collateral below the 10 USDC minimum (100000000 raw), or the open fee consumed all of it. Send collateral as a 7-decimal fixed-point string.
  • #21 InvalidLeverage: leverage must be an integer from 1 to 10 on the current deployment.
  • #23 PositionTooLarge: position size (collateral times leverage) above the $100,000 cap (maxPositionSize in GET /v1/markets/stats).
  • #82 OpenInterestCapExceeded and #89 SkewCapExceeded: the open would push the asset past its per-side open-interest cap, the vault's aggregate reservation cap, or its net-skew cap. GET /v1/markets/stats reports the live headroom per asset; reduce size or wait for open interest to unwind.
  • #81 PriceDeviationTooHigh: the fresh price moved more than the deviation band (1% by contract default) from the last good price recorded within ten staleness windows (600 seconds at the 60-second default); opens halt, closes still work.

Parameter details are on Trading mechanics.

Market and shared contract errors (NoetherError)

Shared by the market contract, the Liquidity Vault, the Noeracle shim and the Noether Router. Codes are grouped in ranges by category. This is the enum in the deployed market contract's interface; the numbers 51, 63 and 68 are intentionally unused and never reassigned.

General (1 to 19)

CodeNameMeaning
1NotInitializedContract not initialized
2AlreadyInitializedinitialize called twice
3UnauthorizedCaller not authorized for this operation
4PausedOperation blocked while the contract is paused
5InvalidParameterBad input
6OverflowArithmetic overflow
7DivisionByZeroDivision by zero

Position (20 to 29)

CodeNameMeaning
20PositionNotFoundNo position with that id
21InvalidLeverageLeverage outside 1 to the market's maximum (10 on this deployment)
22InsufficientCollateralCollateral below the 10 USDC minimum, or the open fee consumed all collateral
23PositionTooLargePosition size above the maximum position size
24NotPositionOwnerCaller is not the position's trader
25InsufficientMarginPosition has insufficient margin for the operation
27PositionTooSmallA partial close or reduce-only would leave a residual position below the minimum collateral floor; close the whole position instead

Oracle (30 to 39)

CodeNameMeaning
30PriceStalePrice older than the staleness limit (60 seconds) on a risk-increasing path; closes and liquidations are exempt
31InvalidPricePrice is zero or negative
32OracleUnavailableOracle not responding or unavailable

Vault (40 to 49)

CodeNameMeaning
40InsufficientLiquidityThe Liquidity Vault cannot cover the request (withdrawal above balance, a withdrawal that would undercut reserved payouts, or a reservation above the vault's USDC balance)
41InvalidAmountAmount is zero or negative
42InsufficientBalanceBalance too low for the operation
43DepositCapExceededDeposit would exceed the per-account guarded-launch cap

Liquidation and funding (50 to 59)

CodeNameMeaning
50NotLiquidatablePosition is healthy and cannot be liquidated
55FundingIntervalNotElapsedapply_funding called before 3,600 seconds have elapsed since the last application

Order (60 to 75)

CodeNameMeaning
60OrderNotFoundNo order with that id
61OrderNotPendingOrder already executed or cancelled
62OrderNotTriggeredPrice has not reached the order's trigger
64NotOrderOwnerCaller is not the order's trader
65InvalidTriggerPriceTrigger price invalid (for example a stop-loss above entry for a long)
66InvalidSlippageToleranceSlippage tolerance is 0 or above 10,000 bps
67OrderAlreadyExistsThe position already has an attached order of that type
69InvalidTrailingPercentTrailing percentage outside 1 to 5,000 bps (0.01% to 50%)
70PostOnlyViolationA post-only order would execute immediately at placement

A slippage breach on execution does not raise an error: the order is cancelled with status CancelledSlippage and the collateral refunded.

Cross margin and risk controls (76 to 93)

CodeNameMeaning
76CrossMarginInsufficientBalanceCross-margin pool has insufficient balance for the operation
77CrossMarginInsufficientFreeMarginThe withdrawal or open would leave insufficient free margin
78CrossMarginNotLiquidatableCross-margin account is not liquidatable
79CrossMarginNoPositionsTrader has no open cross-margin positions
80CrossMarginOrderNotSupportedStop-loss, take-profit and trailing stops cannot attach to cross-margin positions
81PriceDeviationTooHighFresh price moved beyond the deviation band versus the stored last-good price; opens halt, closes and liquidations stay allowed
82OpenInterestCapExceededThe open would exceed the per-asset per-side open-interest cap or the aggregate payout-reservation cap (both sized against vault AUM)
83LiquidationCooldownA partial liquidation ran recently and the position is inside its grace period (bankruptcy overrides it)
84AdlNotActiveadl_close called while auto-deleveraging is not active for the position's asset
85AdlNotEligibleThe adl_close target is not a net winner at the current mark
86LiquidationNotConfirmedLiquidation is eligible on the fresh price but not yet confirmed by the smoothed mark; retry next cycle (bankruptcy overrides it)
87AcceptablePriceExceededA market open or close filled worse than the trader's acceptable-price bound; resubmit with 0 to fill unbounded
88AssetRiskNotConfiguredA risk-increasing operation hit an asset with no per-market risk parameters configured
89SkewCapExceededThe open would push the asset's net long-short skew past its cap and make it more imbalanced; skew-reducing opens always pass
90FrozenFull-freeze pause: even risk-reducing operations are halted; only cancel_order works
91NetsToZeroAn open would net to zero or beyond against the trader's opposite same-asset positions; use the close or reduce-only paths instead
92AssetHaltedTrading in this market is temporarily halted by the admin; closing and liquidating still work
93WithdrawCooldownActiveAn LP withdrawal from the Liquidity Vault is inside the post-deposit cooldown window

Trader Vault errors (FactoryError)

Raised by the Trader Vaults (vault factory) contract as deployed. These share numbers with low NoetherError codes; attribute by contract.

CodeNameMeaning
1AlreadyInitializedinitialize called twice
2NotInitializedContract not initialized
3InvalidParameterBad input
4InvalidNameVault name empty or longer than 64 characters
5VaultNotFoundUnknown vault id
6NotLeaderA leader-only call made by an address that is not the vault's leader
7NotAdminDefined; the admin check uses Soroban auth instead, so this code is not raised by the current build
8AmountMustBePositiveAmount or shares is zero or negative
9InsufficientSharesBurning more shares than owned
10InsufficientBalanceTrade collateral or payout exceeds the vault's USDC balance
11LeaderMinimumViolatedThe action would break the leader minimum-holding rule (checked on deposits, withdrawals and leader opens)
12PausedVault is paused by its leader or the admin
13OverflowChecked-math overflow
14NavCalculationFailedNegative inputs to the NAV calculation
15NoFeesToClaimFee claim with NAV at or below the high-water mark
16NotVaultPositionA leader operation referenced a position or order not owned by its vault
17LiquidityDeployedThe withdrawal is priced fairly at full NAV but exceeds the vault's liquid cash while capital is deployed in open positions; wait for the leader to free it
18ValuationUnavailableFull-NAV valuation could not read a position's equity or an order (oracle or market failure); deposits, withdrawals and claims fail closed
19TooManyOpenSlotsThe vault already holds the maximum number of open positions and orders
20CreationRestrictedcreate_vault blocked by the leader allowlist or the maximum-vaults cap
21MinOutputNotMetDeposit or withdraw output fell below the caller's declared minimum; NAV moved between signing and inclusion

See Trader Vaults for the leader minimum-holding rule and how it bounds outside deposits.

Referral errors (ReferralError)

Raised by the referral contract as deployed.

CodeNameMeaning
1AlreadyInitializedinitialize called twice
2NotInitializedContract not initialized
3NotAdminDefined; the admin check uses Soroban auth instead, so this code is not raised by the current build
4NotMarketDefined; the market check uses Soroban auth instead, so this code is not raised by the current build
5InvalidParameterA basis-point parameter above the maximum, or another out-of-range input
6CodeTooShortCode shorter than the minimum length
7CodeTooLongCode longer than the maximum length
8CodeAlreadyTakenCode already exists (codes are globally unique and case-sensitive)
9AlreadyHasCodeOne code per address
10UnknownCodeCode does not resolve to a referrer
11AlreadyHasReferrerReferee is already bound to a referrer; bindings are permanent
12SelfReferralCode owner and referee are the same address
13InsufficientVolumeThe address has not traded the minimum volume required to register a code (the minimum is 0 on the current deployment)
14NothingToClaimClaimable balance is zero
15OverflowChecked-math overflow
16ClaimUnfundedThe registry's USDC balance cannot cover the claim; the claimable balance is preserved, retry once the pool refills
17RegistryPausedRegistry paused by the admin; state-changing calls reject
18RevokedCodeThe code's referrer has been revoked

Next steps

On this page