接 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 和你以为用的不是同一个。 常见三种:
- key 打错、或已经 revoke;
- 环境变量里的 key 是空的;
- 优先级搞反——如果同时存在
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 来源:
score只给了 1 个等级(要 ≥2);choice的criteria写成了数组(它要的是 map);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 这类会被拒。
解析结果时的三个坑
报错之外,还有几个「不报错但结果不对」的坑:
noul没有 confidence 字段。 只有choice才有confidence和probabilities(和为 1);noul只返回 0~1 的noul值,别去取 confidence。- 一定要 log 返回的
model版本。 响应里的model是「真正回答你的那个版本」(如jev-1.13.0),不是你可能传的jev-latest。线上出问题时,这行日志就是证据。 - 只有 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 混合架构》。)