Errors & Rejection Reasons
Complete catalog of error codes and rejection reasons.
Error Response Format
HTTP Error Responses (Middleware)
Structured JSON errors from middleware (HTTP 4xx/5xx):
{
"error": "<code>",
"message": "<human message>"
}
Engine-Level Rejections (HTTP 200)
Trading rejections return HTTP 200 with OrderUpdateMessage.status = "REJECTED":
{
"timestamp": 1735000000000,
"info": { ... },
"status": "REJECTED",
"reason": "<exact rejection string>",
"filled_size": 0,
"order_id": null,
"wallet_address": "0x...",
"mmp_triggered": false
}
Critical: Do not rely on HTTP status codes for trading rejections. Always check status and reason fields.
Middleware Error Codes
These are returned as HTTP error responses with structured JSON body.
| Code | HTTP Status | Description |
|---|---|---|
invalid_request | 400 | Cannot read request body |
invalid_json | 400 | JSON parse failed |
missing_field | 400 | Required field missing |
invalid_wallet | 400 | Wallet string could not be parsed |
invalid_parameter | 400 | Invalid parameter (e.g., size/price must be string) |
signature_verification_failed | 400 | EIP-712 signature recovery failed |
unsupported_endpoint | 400 | Middleware does not support this path |
unauthorized | 401 | Signer is not authorized for wallet (agent auth failed) |
internal_error | 500 | Agent authorization check failed unexpectedly |
Engine Rejection Reasons
These appear in OrderUpdateMessage.reason when status="REJECTED".
Expired Instrument
Reason: "Instrument has expired"
Cause: Order placed on an instrument that has already expired.
Action: Check instrument expiry via GET /instruments or GET /markets.
Unfunded Account
Reason: "Account has no funds. Please deposit before trading."
Cause: Account cash balance is <= 0.0.
Notes:
- New accounts may start with a default test balance (
10_000_000USDC) - Production deposit flow not yet implemented
Insufficient Margin
Reason: "Insufficient margin: worst case margin={:.2} (failing scenario: {ScenarioType})"
Example: "Insufficient margin: worst case margin=-12.34 (failing scenario: SpotChange)"
Cause: Pre-trade margin check found worst_loss + cash < 0 in at least one scenario.
Scenario types:
SpotChange: Spot price movementVolChange: Volatility changeSkewChange: Skew changeKurtosisChange: Kurtosis change
Action:
- Check portfolio via
GET /portfolio?wallet=... - Review margin calculation in Margin
- Reduce position size or add collateral
Missing Spot Price
Reason: "Failed to get portfolio: No spot price available for underlying: {underlying}"
Cause: Engine cannot infer spot price for underlying needed to simulate fills.
Action: Check Hyperliquid spot price feed connectivity. Spot prices come from allMids WebSocket feed.
Tier Restrictions
Reason: "Tier1 users cannot go short. Filled long position: {filled}, total sell orders (including new): {total} (symbol: {symbol})"
Cause: Wallet is tier1 (long-only) and attempted to sell without sufficient filled long position.
Action:
- Check tier via
GET /user-tier?wallet=... - Upgrade to
tier2viaPOST /user-tier(requires admin or signature) - Or ensure all sells are covered by filled long positions
Invalid Symbol
Reason: "Invalid symbol: {symbol}"
Cause: No orderbook exists for the symbol.
Action:
- Verify market exists via
GET /instrumentsandGET /markets - Check symbol format:
UNDERLYING-YYYYMMDD-STRIKE-(C|P)
Symbol Parse Error
Reason: "Failed to parse symbol: {detail}"
Cause: Symbol does not match expected format.
Action: Verify symbol format matches UNDERLYING-EXPIRY-STRIKE-(C|P) or Deribit-style DDMMMYY.
Cancel Failures
Order Not Found
Reason: "Order not found for cancellation: {client_id}"
Cause: Order with given client_id not found.
Action: Verify client_id is correct and order exists via GET /orders?wallet=....
Orderbook Not Found
Reason: "Orderbook not found for symbol: {symbol}"
Cause: Orderbook does not exist for the symbol.
Action: Verify symbol is valid and market exists.
Order Not in Orderbook
Reason: "Order {id} not found in orderbook {symbol}"
Cause: Order ID exists but order is not in the orderbook (may be filled/canceled).
Action: Check order status via GET /orders?wallet=....
Order Already Filled
Reason: "Order {id} is already filled and cannot be cancelled"
Cause: Order was fully filled before cancel request.
Action: Check order status via GET /orders?wallet=....
Order Already Canceled
Reason: "Order {id} was already cancelled"
Cause: Order was already canceled.
Action: Check order status via GET /orders?wallet=....
Perp Order Validation
Reason: "Perp order missing underlying symbol"
Cause: Perp order does not include underlying field.
Action: Ensure perp order includes underlying symbol.
MMP Triggered
Reason: "MMP triggered during fill processing"
Cause: MMP limits breached during fill processing. Order was partially filled, then MMP triggered and canceled remaining quantity.
Action:
- Check MMP config via
GET /mmp-config?wallet=...¤cy=... - Review fill window metrics
- Adjust MMP limits or reset MMP state via
POST /mmp-config/reset
See MMP for full MMP semantics.
MMP Cancel (Other Orders)
Reason: "Order canceled by MMP trigger"
Cause: Order was canceled because another order for the same wallet+underlying triggered MMP.
Action: Review MMP configuration and fill activity.
Handler-Level Validation Errors
These return HTTP 400 before reaching the engine.
Price Validation
Error: "Price validation failed: Price {price} has {n} significant figures, maximum allowed is 5"
Cause: Price exceeds 5 significant figures.
Action: Round price to ≤ 5 significant figures.
Size/Price Format
Error: "Size must be greater than 0" or "Price must be greater than 0"
Cause: Size or price is <= 0 or cannot be parsed as float.
Action: Ensure size and price are valid positive numbers (as strings).
Invalid Symbol Format
Error: HTTP 400 with handler error message
Cause: Symbol does not parse as valid option symbol.
Action: Verify symbol format: UNDERLYING-YYYYMMDD-STRIKE-(C|P).
Bulk Order Errors
Bulk endpoints return per-item errors in BulkOrderResult.error:
"Signature verification failed: ...""Unauthorized: signer not authorized for wallet""Price validation failed: ...""Size must be greater than 0""Price must be greater than 0""Failed to send order to engine""No response from engine"
Each result includes index (position in request array) and success boolean.
WebSocket Errors
WebSocket control messages:
{
"type": "Error",
"message": "Authentication required for this channel"
}
Common errors:
"Authentication required for this channel": Attempted to subscribe to private channel without?wallet="Client not found": Internal error (connection lost)
Error Handling Best Practices
- Always check
statusfield: Do not rely on HTTP status codes for trading rejections - Parse
reasonstring: Use exact reason strings for programmatic handling - Handle bulk errors: Check
BulkOrderResult.errorfor each item in bulk requests - Retry logic: Do not retry on
REJECTEDorders (fix the underlying issue first) - Logging: Log full
OrderUpdateMessagefor debugging rejections
Error Code Reference Table
| Rejection Reason | Category | HTTP Status | Action |
|---|---|---|---|
Instrument has expired | Expiry | 200 | Check expiry, use different instrument |
Account has no funds... | Funding | 200 | Deposit funds (when implemented) |
Insufficient margin: ... | Margin | 200 | Reduce size, add collateral, check portfolio |
Failed to get portfolio: No spot price... | Data | 200 | Check Hyperliquid feed connectivity |
Tier1 users cannot go short... | Tier | 200 | Upgrade to tier2 or cover sells |
Invalid symbol: ... | Symbol | 200 | Verify market exists |
Order not found for cancellation: ... | Cancel | 200 | Verify order exists |
Order {id} is already filled... | Cancel | 200 | Order already executed |
Order {id} was already cancelled | Cancel | 200 | Order already canceled |
MMP triggered during fill processing | MMP | 200 | Review MMP config, adjust limits |
Order canceled by MMP trigger | MMP | 200 | Review MMP config, adjust limits |
signature_verification_failed | Auth | 400 | Check signature, string encoding |
unauthorized | Auth | 401 | Approve agent or sign with wallet |
Price validation failed: ... | Validation | 400 | Round price to ≤ 5 sig figs |
Debugging Rejections
- Check order details: Verify
symbol,price,size,sideare correct - Check portfolio:
GET /portfolio?wallet=...to see current positions and cash - Check tier:
GET /user-tier?wallet=...to verify tier restrictions - Check MMP:
GET /mmp-config?wallet=...¤cy=...to review MMP limits - Check market:
GET /marketsandGET /instrumentsto verify instrument exists - Review logs: Server logs may contain additional context (not exposed via API)
References
- Rejection logic: enforced in the trading engine
- Margin checks: applied before order admission
- Tier checks: enforced per wallet tier
- Handler validation: standard request validation