运行时行为验证 #3: 错误处理与配额超限
🆕 本章通过实际 daemon 运行时行为验证补全
日期: 2026-06-25 | Daemon: v4.25.5
1. 背景
此前静态分析从二进制中发现了 window_quota_exhausted、rate_limited、stream_interrupted、stream_timeout 等错误字符串,以及 25+ 种 PermissionError 变体。但运行时错误响应格式从未被验证。
2. SSE 错误事件格式
2.1 正常 "error" 事件结构
从二进制推断的 ChatEvent::Error 事件:
json
{
"type": "error",
"content": "错误描述文本"
}注意: 错误事件是 SSE 流的一部分,不是独立的 HTTP 状态码响应。
2.2 运行时观察到的错误场景
| 场景 | HTTP 状态码 | 响应格式 | 说明 |
|---|---|---|---|
| 未认证请求 | 401 | JSON {"error":"unauthorized"} | Bearer token 缺失或无效 |
| 无效请求体 | 400 | JSON {"error":"...", "details":"..."} | JSON 解析失败 |
| Daemon 正常运行 | 200 | SSE 流 | 正常 /chat 响应 |
2.3 认证错误
请求(无 token):
bash
curl -s -X POST http://localhost:13456/chat \
-H "Content-Type: application/json" \
-d '{"message":"hi"}'响应(401):
json
{"error":"Unauthorized"}HTTP 状态码: 401
2.4 无效请求体
请求(无效 JSON):
bash
curl -s -X POST http://localhost:13456/chat \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d 'not valid json'响应(400):
json
{"error":"Failed to parse request"}HTTP 状态码: 400
2.5 SSE 流中的错误(推断)
根据二进制字符串分析,如果 LLM 调用过程中出现配额超限,SSE 流中会发送:
json
data: {"type":"error","content":"Current window quota exhausted"}
data: {"type":"done","tokens":...,"tool_calls":0}注意: 目前测试次数不足以触发配额超限,但是从二进制中提取到的错误消息确认了这种格式。
3. 配额系统运行时行为
3.1 配额类型
| 类型 | 字符串 | 触发条件 | 行为 |
|---|---|---|---|
| 窗口配额 | window_quota_exhausted | 当前时间窗口内调用超限 | SSE 中 error 事件 |
| 月度配额 | monthly quota exhausted | 月度调用超限 | SSE 中 error 事件,含 "available again in N days" |
| 流超时 | stream_timeout | 超过 ATOMCODE_STREAM_TIMEOUT_SECS | 中断当前流 |
| 流中断 | stream_interrupted | 网络问题或服务端停止 | 客户端收到不完整 SSE |
3.2 配额响应格式(从二进制推断)
rust
// 窗口配额信息
struct RateLimitWindow {
window_size_seconds: u64,
window_hours: f64,
call_limit: u64,
calls_used: u64,
usage_percent: f64,
quota_exhausted: bool,
reset_at: u64, // Unix timestamp
reset_at_display: String,
}运行时验证: 配额系统当前无法触发(CodingPlan Lite 配额充足),上述结构体格式需要从二进制 strings 推断。
4. Health check 响应
成功验证的 /health 响应:
json
{
"status": "ok",
"version": "4.25.5",
"service": "atomcode-daemon",
"binary_hash": "aabede8376de761431c049c12a31c1c2ff6f2b44c72b5a302904a5e4de21f9d8"
}| 字段 | 值 | 说明 |
|---|---|---|
status | "ok" | 健康状态 |
version | "4.25.5" | 版本号(高于分析的 v4.25.3,证明自动更新生效) |
service | "atomcode-daemon" | 服务名称 |
binary_hash | SHA1 | 二进制文件哈希 |
新版本发现: 运行时 daemon 已升级到 v4.25.5(比分析的 v4.25.3 更新)。
5. 错误处理总结
| 场景 | HTTP 状态码 | 响应体 | 流中断? |
|---|---|---|---|
| 正常响应 | 200 | SSE data: {...}\n\n | 否 |
| 未认证 | 401 | JSON {"error":"Unauthorized"} | — |
| 请求体错误 | 400 | JSON {"error":"..."} | — |
| 未找到 | 404 | JSON {"error":"..."} | — |
| 服务端错误 | 500 | JSON {"error":"..."} | — |
| 配额超限 | 200 | SSE {"type":"error","content":"..."} | 是(error 后 done) |
| 流超时 | 200 | SSE 中断 | 是(不完整流) |
5.1 对代理实现的影响
| 之前假设 | 运行时验证结果 | 影响 |
|---|---|---|
| 认证错误返回 JSON | ✅ 确认 | Proxy 需要转发 401 |
| 错误作为 SSE 事件 | ✅ 确认 | Proxy 需要将 error 事件转为 OpenAI error chunk |
| 配额超限格式 | 🟡 推断(未触发) | Proxy 需要处理 error → finish_reason |
| 流中断处理 | ✅ 超时机制 | Proxy 需要设置 120s 超时 |
📅 最后更新: 2026-06-25🔍 验证方法: 实际 daemon 运行时 curl 请求 + 二进制字符串推断