Featured image of post Jev 报错排查完全指南:401、422、429、529 一次讲透!

Jev 报错排查完全指南:401、422、429、529 一次讲透!

接 Jev 的时候,最烦的往往不是它判错,而是它直接甩给你一个冷冰冰的 HTTP 状态码。

这篇把我碰到过的、和社区里被问得最多的几类 Jev 报错,按「症状 → 原因 → 修复」理一遍。目标是让你下次看到 401、422、429、529 的时候,不用再翻帖子。

先把最常见的五个症状列出来:

  • 调用直接 401:Cannot authenticate with the server. Please check your API key and try again.
  • 422 Validation failed,但看不出 payload 哪里不对
  • 白天正常,晚上开始 429 刷屏
  • 偶发 529 Overloaded
  • SDK 明明装好了,还是报「找不到 key」

(还没装 Jev?先看 《Jev 安装完全指南》。想先搞懂它是什么,看 《TypeSafe AI Jev 深度解析》。)

先记住:Jev 只有四个错误码

Jev 的 API 面小到能背下来——只有一个端点 POST https://api.typesafe.ai/v1/systemone(外加一个 GET /v1/models)。对应的错误码也只有四个:

状态 含义 该不该重试
401 Auth failed(认证失败) 不要重试
422 Validation failed(校验失败) 不要重试
429 Rate limited(被限流) 指数退避
529 Overloaded(服务过载) 退避 + 熔断

一句话:401 和 422 是「你的问题」,重试一万次也没用;429 和 529 是「时机问题」,退避重试才对。

401:认证失败——先别改代码,先查 key

最高频的一个。完整报错长这样:

Error: the TypeSafe API rejected the credential (HTTP 401):
Cannot authenticate with the server. Please check your API key and try again.

原因几乎总是同一个:你实际用的 key 和你以为用的不是同一个。 常见三种:

  1. key 打错、或已经 revoke;
  2. 环境变量里的 key 是空的;
  3. 优先级搞反——如果同时存在 JEV_API_KEY 和 TYPESAFE_API_KEY,前者优先级更高。你在 jev auth login 存了 A,但环境变量 B 把 A 盖住了。

排查三步:

# 1. 看 CLI/SDK 到底认了哪个来源
jev auth status

# 2. 不花 token 地验一下 key
jev doctor --live

# 3. 直接 curl 验
curl -s -o /dev/null -w "%{http_code}\n" \
  -H "Authorization: Bearer $TYPESAFE_API_KEY" \
  https://api.typesafe.ai/v1/models

/v1/models 返回 200,说明 key 是好的——那问题就在你代码取 key 的方式。返回 401,就重新生成一枚 key。

422:校验失败——对照 schema 逐字段看

422 是「你发出去的 payload 不合法」,而且它不会告诉你哪里错,只能自己对。

Jev 的请求体只有三个顶层字段:model、state、questions。没有别的。 记住这一条就能排掉大半 422:

  • 没有 temperature、top_p、max_tokens
  • 没有 stream
  • 没有 system、metadata

如果你是从别的 LLM API 抄过来的请求体,这些字段一放进去就是 422。

再看 questions 三种类型各自的硬约束:

类型 criteria 约束
choice 选项 map,最多 255 个
score 有序等级数组,至少 2、最多 10
noul 可选 {true, false},不填也行

最常见的三个 422 来源:

  1. score 只给了 1 个等级(要 ≥2);
  2. choice 的 criteria 写成了数组(它要的是 map);
  3. state 太大——官方限制是每次请求 ≤64k tokens,且 state + 最长的那一个问题 ≤32k tokens,超了就是 422。

⚠️ 顺带一提:官方文档在 context 上自己打架——Primitives 页说共享预算「约 32k」,Models 页说 64k 总量 / 32k state。保守起见按 32k 算。

429 / 529:限流与过载——退避,但别无脑退避

这两个是真正的「等一下就好」。

官方限流数值(可能随时变):

  • 250,000 tokens/秒
  • 1,200 请求/分钟

任一超限就返回 429;服务端整体过载返回 529。

退避曲线(官方建议):1s → 2s → 4s,加 jitter,并设一个整体超时。529 在持续失败时建议熔断,别让它拖垮你的服务。

两个官方 SDK 都自带可配置的 RetryPolicy,默认值已经好用:max_retries=2、初始 0.5s 翻倍到最多 5.0s、jitter 0.25、可重试状态 408/429/500-599、总预算 timeout=30.0。

但有个坑:如果你自己的队列/任务系统已经有重投递,一定要把 SDK 的 retry 关掉:

from typesafe_sdk import RetryPolicy, TypeSafeClient

client = TypeSafeClient(retry=RetryPolicy(max_retries=0))

两层重试叠在一起,会把一个短暂的 429 放大成 stampede。这是很多人第一次上量时踩的坑。

SDK / CLI:找不到 key、key 为空、存不进凭证

如果你用官方 CLI(jev),它的报错其实很贴心,exit 3 基本都和凭证有关:

  • no TypeSafe API key found——它找遍了 JEV_API_KEY、JEV_API_KEY_FILE、TYPESAFE_API_KEY 和系统凭证库,都没有。
  • the API key found in … is empty——变量被设成了空白。这几乎总是 CI 密钥没替换成功(secret 名打错,或 fork 里拿不到 secret)。
  • secure credential storage is unavailable——没有可用的系统凭证库。headless Linux / 容器 / SSH 里很常见。它不会退化成明文文件,直接用环境变量。
jev auth login                # 交互式,存进系统凭证库
export JEV_API_KEY="sk-..."   # CI / headless
jev doctor                    # 看每个设置从哪来(不发网络请求、不打印 key)

还有一个 exit 2:refusing to send a credential over plain HTTP——只有明确的回环地址才允许 http,localhost.example.com 这类会被拒。

解析结果时的三个坑

报错之外,还有几个「不报错但结果不对」的坑:

  1. noul 没有 confidence 字段。 只有 choice 才有 confidence 和 probabilities(和为 1);noul 只返回 0~1 的 noul 值,别去取 confidence。
  2. 一定要 log 返回的 model 版本。 响应里的 model 是「真正回答你的那个版本」(如 jev-1.13.0),不是你可能传的 jev-latest。线上出问题时,这行日志就是证据。
  3. 只有 input 计费。 usage 里有 output_tokens,但只收 input 的钱——别看到 output 就以为在烧钱。

不要踩的坑(一张清单)

  • 别往请求里塞 temperature / stream / max_tokens → 422
  • 别指望有 streaming / batch / async 端点 → 没有,全同步返回
  • 别在已有重投递的队列上开 SDK retry → 429 会被放大
  • 别只按 64k 上限塞 state → 保守按 32k
  • 别硬编码 key → 用环境变量
  • 别把 choice 的 criteria 写成数组 → 它要 map

修好之后怎么验证

jev doctor --live        # 加一次最小 API 调用,确认链路通

再用一个最小请求打一发:

curl -s https://api.typesafe.ai/v1/systemone \
  -H "Authorization: Bearer $TYPESAFE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"jev-latest","state":"hello","questions":{"ok":{"type":"noul","instructions":"this request is well-formed"}}}'

返回里带 answers.ok 就说明通了。

FAQ

Q:401 换了 key 还是不行? A:八成是环境变量优先级——旧 key 还在 JEV_API_KEY 里盖着新的。跑 jev auth status 看谁赢了。

Q:jev-latest 和 jev-1.13.0 该用哪个? A:生产用带版本号的(可复现),试想法用 jev-latest。响应里的 model 会告诉你实际用了哪个。

Q:为什么 noul 拿不到 confidence? A:设计如此。noul 返回的 0~1 本身就是 yes 概率,不再单独给 confidence。

Q:延迟 70–500ms 是 SLA 吗? A:不是。这个数字只出现在发布博客里,官方文档没有 SLA、没有分位数。别拿它做容量规划。

Q:非英文输入会怎样? A:官方说以英文为主,其他语言「可以接受但准确率更低」。中文场景建议自己压测校准质量。

Q:能微调吗? A:不能。同一份权重服务所有账户,没有 fine-tuning API。

写在最后

Jev 的 API 面小到能背下来——一个端点、三种问题类型、四个错误码。这既是优点(好学),也意味着大部分报错只来自那么几个地方:key 没对上、payload 混进了别的 LLM 的字段、或者没做好退避。

把这篇当成一张速查表存着。下次 Jev 报错,先看状态码是 4xx「你的问题」还是可以退避的「时机问题」,再往下查。

(相关阅读:《TypeSafe AI Jev 深度解析》、《Jev 安装完全指南》、《决策模型 + LLM 混合架构》。)

By AI博士 万戈