错误与拒绝原因
错误代码和拒绝原因的完整目录。
错误响应格式
HTTP 错误响应(中间件)
来自中间件的结构化 JSON 错误(HTTP 4xx/5xx):
{
"error": "<code>",
"message": "<human message>"
}
引擎级拒绝(HTTP 200)
交易拒绝返回 HTTP 200,且 OrderUpdateMessage.status = "REJECTED":
{
"timestamp": 1735000000000,
"info": { ... },
"status": "REJECTED",
"reason": "<exact rejection string>",
"filled_size": 0,
"order_id": null,
"wallet_address": "0x...",
"mmp_triggered": false
}
重要:请勿依赖 HTTP 状态码来判断交易拒绝。请始终检查 status 和 reason 字段。
中间件错误代码
这些错误以带结构化 JSON 正文的 HTTP 错误响应形式返回。
| 代码 | HTTP 状态 | 描述 |
|---|---|---|
invalid_request | 400 | 无法读取请求正文 |
invalid_json | 400 | JSON 解析失败 |
missing_field | 400 | 缺少必填字段 |
invalid_wallet | 400 | 钱包字符串无法解析 |
invalid_parameter | 400 | 无效参数(例如 size/price 必须为字符串) |
signature_verification_failed | 400 | EIP-712 签名恢复失败 |
unsupported_endpoint | 400 | 中间件不支持此路径 |
unauthorized | 401 | 签名者未获得该钱包的授权(代理身份验证失败) |
internal_error | 500 | 代理授权检查意外失败 |
引擎拒绝原因
当 status="REJECTED" 时,这些内容会出现在 OrderUpdateMessage.reason 中。
已到期的合约
原因:"Instrument has expired"
成因:在已到期的合约上下单。
处理方法:通过 GET /instruments 或 GET /markets 检查合约到期日。
账户无资金
原因:"Account has no funds. Please deposit before trading."
成因:账户现金余额 <= 0.0。
处理方法:在交易前向钱包充值 USDC。
保证金不足
原因:"Insufficient margin: required={:.2}, available={:.2}, shortfall={:.2}"
示例:"Insufficient margin: required=1500.00, available=1200.00, shortfall=300.00"
成因:交易前保证金检查发现可用抵押品(净值)不足以覆盖拟下订单后的保证金要求。
对于标准保证金账户,所需抵押品取决于期权方向、期权类型、行权价、标的资产价格和当前投资组合。有关当前上线的保证金模型,请参阅标准保证金。
处理方法:
- 通过
GET /portfolio?wallet=...检查投资组合 - 在保证金中查看保证金计算方式
- 减少仓位规模或增加抵押品
缺失现货价格
原因:"Failed to get portfolio: No spot price available for underlying: {underlying}"
成因:引擎无法获取模拟成交所需的标的资产现货价格。
处理方法:检查 Hyperliquid 现货价格数据源的连接性。现货价格来自 allMids WebSocket 数据流。
层级限制
原因:"Tier1 users cannot go short. Filled long position: {filled}, total sell orders (including new): {total} (symbol: {symbol})"
成因:钱包为 tier1(仅限做多),在没有足够已成交多头仓位的情况下尝试卖出。
处理方法:
- 通过
GET /user-tier?wallet=...检查层级 - 确保所有卖出都由已成交的多头仓位覆盖
- 如果您需要做市商集成的卖方(writer)权限,请联系 Hypercall
无效合约代码
原因:"Invalid symbol: {symbol}"
成因:该合约代码不存在对应的订单簿。
处理方法:
- 通过
GET /instrument-specs和GET /markets验证市场是否存在 - 检查合约代码格式:
UNDERLYING-YYYYMMDD-STRIKE-(C|P)
合约代码解析错误
原因:"Failed to parse symbol: {detail}"
成因:合约代码不符合预期格式。
处理方法:验证合约代码格式是否符合 UNDERLYING-EXPIRY-STRIKE-(C|P) 或 Deribit 风格的 DDMMMYY。
撤单失败
订单未找到
原因:"Order not found for cancellation: {client_id}"
成因:未找到具有给定 client_id 的订单。
处理方法:验证 client_id 是否正确,并通过 GET /orders?wallet=... 确认订单存在。
订单簿未找到
原因:"Orderbook not found for symbol: {symbol}"
成因:该合约代码不存在对应的订单簿。
处理方法:验证合约代码有效且市场存在。
订单不在订单簿中
原因:"Order {id} not found in orderbook {symbol}"
成因:订单 ID 存在,但订单不在订单簿中(可能已成交/已撤销)。
处理方法:通过 GET /orders?wallet=... 检查订单状态。
订单已成交
原因:"Order {id} is already filled and cannot be cancelled"
成因:订单在撤单请求前已完全成交。
处理方法:通过 GET /orders?wallet=... 检查订单状态。
订单已撤销
原因:"Order {id} was already cancelled"
成因:订单已被撤销。
处理方法:通过 GET /orders?wallet=... 检查订单状态。
永续合约订单验证
原因:"Perp order missing underlying symbol"
成因:永续合约订单未包含 underlying 字段。
处理方法:确保永续合约订单包含 underlying 标的代码。
MMP 触发
原因:"MMP triggered during fill processing"
成因:在成交处理过程中突破了 MMP 限制。订单已部分成交,随后 MMP 触发并撤销了剩余数量。
处理方法:
- 通过
GET /mmp-config?wallet=...¤cy=...检查 MMP 配置 - 查看成交窗口指标
- 调整 MMP 限制或通过
POST /mmp-config/reset重置 MMP 状态
有关完整的 MMP 语义,请参阅 MMP。
MMP 撤单(其他订单)
原因:"Order canceled by MMP trigger"
成因:该订单被撤销,因为同一钱包+标的资产的另一笔订单触发了 MMP。
处理方法:检查 MMP 配置和成交活动。
处理器级验证错误
这些错误在到达引擎之前返回 HTTP 400。
价格验证
错误:"Price validation failed: Price {price} has {n} significant figures, maximum allowed is 5"
成因:价格超过 5 位有效数字。
处理方法:将价格四舍五入至 ≤ 5 位有效数字。
数量/价格格式
错误:"Size must be greater than 0" 或 "Price must be greater than 0"
成因:数量或价格 <= 0 或无法解析为浮点数。
处理方法:确保 size 和 price 为有效的正数(以字符串形式提供)。
无效合约代码格式
错误:HTTP 400 并附带处理器错误消息
成因:合约代码无法解析为有效的期权合约代码。
处理方法:验证合约代码格式:UNDERLYING-YYYYMMDD-STRIKE-(C|P)。
批量订单错误
批量端点会在 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"
每个结果都包含 index(在请求数组中的位置)和 success 布尔值。
WebSocket 错误
WebSocket 控制消息:
{
"type": "Error",
"message": "Authentication required for this channel"
}
常见错误:
"Authentication required for this channel":尝试在没有?wallet=的情况下订阅私有频道"Client not found":内部错误(连接丢失)
错误处理最佳实践
- 始终检查
status字段:请勿依赖 HTTP 状态码判断交易拒绝 - 解析
reason字符串:使用精确的原因字符串进行程序化处理 - 处理批量错误:检查批量请求中每个条目的
BulkOrderResult.error - 重试逻辑:不要对
REJECTED订单重试(请先修复根本问题) - 日志记录:记录完整的
OrderUpdateMessage以便调试拒绝
错误代码参考表
| 拒绝原因 | 类别 | HTTP 状态 | 处理方法 |
|---|---|---|---|
Instrument has expired | 到期 | 200 | 检查到期日,使用其他合约 |
Account has no funds... | 资金 | 200 | 充值资金(功能实现后) |
Insufficient margin: ... | 保证金 | 200 | 减少数量、增加抵押品、检查投资组合 |
Failed to get portfolio: No spot price... | 数据 | 200 | 检查 Hyperliquid 数据源连接性 |
Tier1 users cannot go short... | 层级 | 200 | 升级到 tier2 或覆盖卖单 |
Invalid symbol: ... | 合约代码 | 200 | 验证市场是否存在 |
Order not found for cancellation: ... | 撤单 | 200 | 验证订单是否存在 |
Order {id} is already filled... | 撤单 | 200 | 订单已执行 |
Order {id} was already cancelled | 撤单 | 200 | 订单已撤销 |
MMP triggered during fill processing | MMP | 200 | 检查 MMP 配置,调整限制 |
Order canceled by MMP trigger | MMP | 200 | 检查 MMP 配置,调整限制 |
signature_verification_failed | 身份验证 | 400 | 检查签名、字符串编码 |
unauthorized | 身份验证 | 401 | 批准代理或使用钱包签名 |
Price validation failed: ... | 验证 | 400 | 将价格四舍五入至 ≤ 5 位有效数字 |
拒绝问题调试
- 检查订单详情:验证
symbol、price、size、side是否正确 - 检查投资组合:使用
GET /portfolio?wallet=...查看当前仓位和现金 - 检查层级:使用
GET /user-tier?wallet=...验证层级限制 - 检查 MMP:使用
GET /mmp-config?wallet=...¤cy=...查看 MMP 限制 - 检查市场:使用
GET /markets和GET /instruments验证合约是否存在 - 查看日志:服务器日志可能包含额外的上下文(不通过 API 暴露)
参考
- 拒绝逻辑:由交易引擎强制执行
- 保证金检查:在订单进入前执行
- 层级检查:按钱包层级强制执行
- 处理器验证:标准请求验证