> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qfex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 错误处理

所有 WebSocket 频道都可能返回**错误帧**，而非预期响应。错误帧共享统一的结构。

## 错误消息封装

```json theme={null}
{
  "err": {
    "error_code": "RateLimited",
    "message": "You have exceeded the allowed message rate.",
    "incoming_message": {
      "type": "add_order",
      "params": {
        "symbol": "AAPL",
        "side": "BUY",
        "order_type": "LIMIT",
        "order_time_in_force": "GTC",
        "quantity": 10.0,
        "price": 200.0,
        "client_order_id": "my-order-001",
        "take_profit": null,
        "stop_loss": null
      }
    }
  }
}
```

### 字段

| 字段 | 类型 | 必填 | 说明 |
| - | - | - | - |
| `error_code` | string | 是 | 机器可读错误代码，见下表；与服务端枚举变体完全一致。 |
| `message` | string/null | 否 | 便于阅读的上下文信息，可以为 `null`。 |
| `incoming_message` | object/null | 否 | 若可用，回传导致错误的原始请求消息。 |

> `incoming_message` 使用与请求相同的带标签格式：`{ "type": "<snake_case>", "params": { ... } }`。

## 错误代码

以下值与服务端枚举一一对应：

| 代码 | 发生情况 | 建议的客户端处理 |
| - | - | - |
| `RateLimited` | 超过允许的消息速率，按消息类型加权计算。 | 退避后重试，考虑批量处理并遵守公布限额。 |
| `InvalidJSONFormat` | 消息不是有效 JSON，或不符合预期模式。 | 发送前验证 JSON 和模式，包含必填字段及正确类型、枚举值。 |
| `AlreadyAuthenticated` | 在同一连接已成功认证后再次认证。 | 不要在已认证连接上重复认证。 |
| `InvalidParameter` | 一个或多个参数超范围、缺失或不适用于该消息。 | 修正参数后重试。 |
| `PermissionDenied` | API 密钥或用户无权执行请求操作。 | 检查密钥范围及角色，必要时联系支持团队。 |
| `ServerError` | 意外的内部错误。 | 短暂等待后重试；持续发生时，向支持团队提供时间戳和 `incoming_message`。 |
| `InvalidOrder` | 订单无效或格式错误。 | 检查并修正订单参数与格式后重试。 |
| `InvalidOrderId` | 提供的订单 ID 无效。 | 检查其是否为有效订单 UUID。 |
| `KycRequired` | 用户需要先完成 KYC。 | 完成 KYC 后重试。 |
| `TncRequired` | 用户需接受最新条款。 | 接受最新条款。 |

### 限流说明

服务器根据消息 `"type"`（例如 `"add_order"`、`"cancel_order"`）计算**消息权重**，并在滑动窗口上应用限制。部分消息权重更高。遇到 `RateLimited` 时，应延迟并降低频率；可行时优先合并为数量更少、内容更集中的请求。

## 示例

### 1. JSON 无效

```json theme={null}
{
  "err": {
    "error_code": "InvalidJSONFormat",
    "message": "Expected field `symbol` (string).",
    "incoming_message": {
      "type": "add_order",
      "params": {
        "side": "BUY",
        "order_type": "LIMIT",
        "order_time_in_force": "GTC",
        "quantity": 10.0,
        "price": 200.0
      }
    }
  }
}
```

### 2. 已经完成认证

```json theme={null}
{
  "err": {
    "error_code": "AlreadyAuthenticated",
    "message": "Connection is already authenticated.",
    "incoming_message": { "type": "auth", "params": {} }
  }
}
```

### 3. 参数无效

```json theme={null}
{
  "err": {
    "error_code": "InvalidParameter",
    "message": "price must be >= min_tick and within price bands.",
    "incoming_message": {
      "type": "modify_order",
      "params": {
        "symbol": "AAPL",
        "order_id": "cd1a2b0c-...-f3",
        "quantity": 10.0,
        "price": 0.0001,
        "take_profit": 0.0,
        "stop_loss": 0.0,
        "side": "BUY"
      }
    }
  }
}
```

### 4. 权限不足

```json theme={null}
{
  "err": {
    "error_code": "PermissionDenied",
    "message": "API key does not allow trading on this account.",
    "incoming_message": {
      "type": "transfer_balance",
      "params": { "amount": 100.0, "to_api_key": "****" }
    }
  }
}
```

### 5. 触发限流

```json theme={null}
{
  "err": {
    "error_code": "RateLimited",
    "message": "Too many requests. Please retry after 200ms.",
    "incoming_message": { "type": "cancel_all_orders", "params": {} }
  }
}
```

### 6. 服务端错误

```json theme={null}
{
  "err": {
    "error_code": "ServerError",
    "message": "Unexpected error processing request.",
    "incoming_message": { "type": "get_user_trades", "params": { "limit": 50 } }
  }
}
```

## 客户端处理模式

> [accordion] Python
>
> ```python theme={null}
> import json
> import websocket
>
> def on_message(ws, message):
>     msg = json.loads(message)
>     if msg.get("type") == "error":
>         code = msg.get("error_code")
>         print(f"[ERROR] {code}: {msg.get('message')}")
>         # basic strategy
>         if code == "RateLimited":
>             # implement backoff before retrying your last request
>             return
>         elif code in ("InvalidJSONFormat", "InvalidParameter"):
>             # fix your payload; don't auto-retry
>             return
>         elif code in ("PermissionDenied", "AlreadyAuthenticated"):
>             # adjust flow; no retry
>             return
>         else:
>             # ServerError or unknown: small backoff and optional retry
>             return
>     else:
>         print("OK:", msg)
> ```

> [accordion] Node
>
> ```javascript theme={null}
> import WebSocket from "ws";
>
> const ws = new WebSocket("wss://trade.qfex.com?api_key=YOUR_API_KEY");
>
> ws.on("message", (raw) => {
>   const msg = JSON.parse(raw.toString());
>   if (msg.type === "error") {
>     const { error_code, message } = msg;
>     console.error(`[ERROR] ${error_code}: ${message || ""}`);
>
>     switch (error_code) {
>       case "RateLimited":
>         // schedule retry w/ backoff
>         break;
>       case "InvalidJSONFormat":
>       case "InvalidParameter":
>         // fix payload, do not blind-retry
>         break;
>       case "PermissionDenied":
>       case "AlreadyAuthenticated":
>         // update client state/flow
>         break;
>       default:
>         // transient server error: optional retry with jitter
>         break;
>     }
>     return;
>   }
>
>   // handle normal messages…
> });
> ```

> [accordion] Go
>
> ```go theme={null}
> type ErrorFrame struct {
>     Type            string          `json:"type"`
>     ErrorCode       string          `json:"error_code"`
>     Message         *string         `json:"message,omitempty"`
>     IncomingMessage json.RawMessage `json:"incoming_message,omitempty"`
> }
>
> func handleMessage(raw []byte) {
>     // peek at "type"
>     var meta struct{ Type string `json:"type"` }
>     if err := json.Unmarshal(raw, &meta); err != nil { return }
>
>     if meta.Type == "error" {
>         var ef ErrorFrame
>         if err := json.Unmarshal(raw, &ef); err == nil {
>             log.Printf("[ERROR] %s: %s", ef.ErrorCode, deref(ef.Message))
>             // handle per code...
>         }
>         return
>     }
>
>     // normal flow...
> }
> ```

## 认证与错误

* `trade.qfex.com` 要求在连接建立后的 1 分钟内完成认证。
* 对已经认证的连接再次认证，会返回 `AlreadyAuthenticated`。

## 排查清单

1. 验证 JSON，包括类型、枚举及必填字段。
2. 遵守速率限制，降低突发流量并尽可能批量处理。
3. 确保 API 密钥拥有正确权限。
4. 记录错误帧中的 `incoming_message`，便于重现问题。
5. `ServerError` 持续发生时，向 **[support@qfex.com](mailto:support@qfex.com)** 提供时间戳及引发错误的 `incoming_message`。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.