给自建服务接 AI 分析能力时,我在 API Key 这一步来回折腾了三次。这篇把实测出的错误码对照表整理出来——都是真实测试结果,不是抄文档。
本文属于 WorkBuddy 实战笔记系列。
给自建的书库服务接 AI 分析能力,需要调大模型 API。按理说这步很简单——注册、拿 Key、填进配置、跑通。
结果在这一步卡了将近一小时,来回折腾了 三次 才成功。
有意思的是:三次失败报的都是 401,但错误码完全不一样,含义也完全不同。 网上搜「大模型 API 401」出来的文章基本只讲「Key 填错了」,实际上远不止这一种情况。
我把实测结果整理成对照表,希望能帮后来的人少走弯路。
错误码 | 报错原文 | 实际含义 | 触发原因 |
|---|---|---|---|
1000 | 身份验证失败 | 格式合法但 Key 查不到 | Key 已被删除,或不是最新的那个 |
401 | 令牌已过期或验证不正确 | 格式不完整 | 只复制了 Key 的一半 |
1004 | 通过 Authentication Token 的验证失败 | Key 被顶掉了 | 同项目下新建了 Key,旧的立即失效 |
这个是误导性最强的。
因为它说的是「身份验证失败」,第一反应一定是「我 Key 填错了」。但实际测下来,格式是对的。
我是这么定位的:故意把 Key 拆成前段和后段分别测试。
Bearer 完整Key(带点) → 1000 身份验证失败
Bearer 只用前段 → 401 令牌已过期或验证不正确
Bearer 只用后段 → 401 令牌已过期或验证不正确关键发现:残缺的 Key 报的是 401,完整的 Key 报的是 1000。
这说明服务端认得 Key 的格式结构(前段.后段),只是这个 Key 在数据库里找不到。
结合平台规则看就明白了:
API Key 仅在创建时完整展示一次,后续无法查看或恢复。
所以 1000 的真实含义是:Key 格式没问题,但这个 Key 不存在了——要么被删了,要么过期了,要么你复制的是好几个版本之前的。
处理办法:直接重新建一个,别在这个 Key 上浪费时间。
这个才是真正的「格式不对」,而且原因往往很隐蔽。
大模型平台的 Key 通常是两段式结构:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxx
└────── 32位十六进制 ──────┘ └─── 一段随机串 ───┘
↑
中间这个点很关键我是怎么踩进去的:从网页复制时,只选中了前半段(鼠标拖选没拖全),后半段漏了。前半段看起来很像一个完整的 Key,所以完全没察觉。
还有一种情况:复制时连带把页面上的说明文字一起复制了。比如页面上写着「密钥」两个字,复制出来的内容就变成 xxxx.xxxx密钥,混入中文直接失效。
处理办法:
我后来养成的习惯是:复制完先数一下,前段 32 位、后段 16 位,对不上就重新复制。
这个最阴,因为它会「先成功后失败」。
我遇到的现象是:
06:08 测试 → 401(旧 Key)
06:12 换新 Key 测试 → 成功 ✅
06:13 用新 Key 跑任务 → 前半段成功,后半段 401
06:14 再测新 Key → 连续 3 次全部 401同一个 Key,几分钟前还很正常,突然就废了。
排查后发现原因:在同一个项目下新建了 Key。
平台的设计逻辑是:一个项目维护一个「当前有效」的凭证。你在网页上点了「新建」之后,之前那个 Key 立即作废——哪怕它刚创建几分钟。
更麻烦的是:如果新建之后你没有把新 Key 复制下来,那个新 Key 也拿不到了(只显示一次),结果就是两边都没了。
处理办法:
这三次踩坑最大的教训是:别用「改配置 → 重启服务 → 看日志」的方式排查,太慢。
正确做法是写个最小验证脚本,直接打 API 端点。我用 Python 标准库写的(不需要装任何依赖):
import json, urllib.request, urllib.error
KEY = "你的key"
URL = "https://open.bigmodel.cn/api/paas/v4/chat/completions"
payload = {
"model": "glm-4-flash",
"messages": [{"role": "user", "content": "回复OK"}],
"max_tokens": 5,
}
req = urllib.request.Request(
URL,
data=json.dumps(payload).encode(),
headers={
"Content-Type": "application/json",
"Authorization": "Bearer " + KEY,
},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=40) as r:
d = json.loads(r.read().decode())
print("OK ->", d["choices"][0]["message"]["content"])
except urllib.error.HTTPError as e:
print("HTTP", e.code)
print(e.read().decode("utf-8", errors="ignore")[:200])这个脚本有三个好处:
我后来加了个连测逻辑,连续调用三次:
ok = 0
for i in range(3):
# ... 调用 ...
if 成功: ok += 1
print("结论:", "稳定可用" if ok == 3 else f"只有 {ok}/3 成功,Key 不稳定")为什么连测三次:因为遇到过「第一次成功、后面全失败」的情况。单次测试会给你虚假的安全感。
第一,把 Key 当作一次性产物。
不要指望它能长期稳定存在。建完就立刻复制、立刻存好、立刻验证。平台上的 Key 列表只是「凭证管理」,不是「凭证仓库」——里面的内容你随时可能拿不回来。
第二,错误码是你的朋友。
401 是个大类,但细分错误码能精确告诉你问题在哪。花五分钟把错误码和含义对上,比盲目重试一百次有用。
第三,验证脚本要能手动拆解。
如果验证脚本只能测「完整 Key 能不能用」,那它只能告诉你「不行」。但如果它能分别测「前段」「后段」「组合」,就能告诉你「为什么不行」。
现象 | 别急着做什么 | 应该先做什么 |
|---|---|---|
401 | 反复重试 | 看错误码 |
1000 | 检查 Key 拼写 | 去平台确认 Key 是否还存在 |
1004 | 怀疑网络 | 确认是否建过新 Key |
这三次踩坑一共花了半小时,但写这个验证脚本只花了五分钟。下次再遇到同类问题,五分钟定位,不用再折腾半小时。
本文记录的是实际调试过程,错误码和现象均来自真实测试。不同平台的错误码定义可能有差异,但排查思路是通用的。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。