Ollama API 错误
Ollama 的错误处理有一条特殊规则:流式响应中途出错时,HTTP 状态码不会变。这是客户端最容易漏处理的地方。
版本基线 v0.40.12,官方
docs.ollama.com/api/errors。
一、状态码
| 码 | 含义 | 常见触发 |
|---|---|---|
200 |
成功 | — |
400 |
请求错误 | 缺参数、JSON 非法 |
404 |
未找到 | 模型不存在 |
429 |
请求过多 | 触发限流 |
500 |
服务端内部错误 | — |
502 |
网关错误 | 云端模型无法访问 |
另外在云端场景还会见到 401(未认证)、402(需付费/余额不足)、413(请求过大)。
二、错误响应体格式
统一是 application/json,错误信息放在 error 属性里:
{
"error": "the model failed to generate a response"
}
结构极简——只有一个字段。不要去找 message 或 code 字段,它们不存在。判断依据只能是 HTTP 状态码 + error 文本。
三、流式中的错误:最关键的一条
如果错误发生在已经开始流式输出之后,响应状态码不会改变(因为响应头和状态行已经发出去了)。错误会作为 NDJSON 的一行出现:
{"model":"gemma4","created_at":"2025-10-26T17:21:21.196249Z","response":" Yes","done":false}
{"model":"gemma4","created_at":"2025-10-26T17:21:21.207235Z","response":".","done":false}
{"model":"gemma4","created_at":"2025-10-26T17:21:21.219166Z","response":"I","done":false}
{"model":"gemma4","created_at":"2025-10-26T17:21:21.231094Z","response":"can","done":false}
{"error":"an error was encountered while running the model"}
注意最后一行的结构:只有 error,没有 model、created_at、done。这意味着:
- 按「每行都有
done字段」写的解析逻辑会在这里崩掉 - 靠「
done: true判断结束」的逻辑会永远等不到结束标记,卡死
正确做法是每一行都先检查 error 键。
四、正确的客户端处理
import json, requests
with requests.post("http://localhost:11434/api/generate", json={
"model": "gemma4",
"prompt": "写一段长文本",
}, stream=True) as r:
# ① 先查 HTTP 状态码(流开始前的错误)
if r.status_code != 200:
raise RuntimeError(f"HTTP {r.status_code}: {r.text}")
buf = []
finished = False
for line in r.iter_lines():
if not line:
continue
chunk = json.loads(line)
# ② 每一行都先检查流内错误
if "error" in chunk:
raise RuntimeError(f"流内错误: {chunk['error']}")
buf.append(chunk.get("response", ""))
# ③ 正常结束标记
if chunk.get("done"):
finished = True
break
if not finished:
# 既没 done 也没 error,说明连接异常断开
print("警告:流未正常结束,结果是部分的")
print("".join(buf))
三段防线分别对应:状态码错误、流内错误、连接中断。
五、按状态码定位问题
| 码 | 排查方向 |
|---|---|
| 400 | 检查 JSON 是否合法、必填字段(model / messages)是否齐全 |
| 404 | ollama list 确认模型存在;云端模型确认名字拼写 |
| 401 | 检查 Authorization: Bearer 头 |
| 402 | 云端模型需付费计划或购买 credits |
| 413 | 请求体过大,常见于多图或超长输入 |
| 429 | 看 Retry-After 头,做指数退避 |
| 500 | 看服务端日志(journalctl -u ollama 或 ~/.ollama/logs/server.log) |
| 502 | 云端模型不可达,通常是网络或上游故障 |
服务端日志的具体位置见 11.1 Ollama 故障排查。
六、重试策略建议
不是所有错误都该重试:
| 码 | 重试 |
|---|---|
| 400 / 404 / 401 / 402 / 413 | 不重试,改请求或改配置 |
| 429 | 重试,按 Retry-After 等待 |
| 500 / 502 | 重试 2–3 次,指数退避 |
盲目重试 400 类错误只会浪费时间和配额。
动手试
故意制造一个 404 和一个流内错误,看清两种错误的形态差别:
## ① 模型不存在 → HTTP 404 + error 字段
curl -i http://localhost:11434/api/chat -d '{
"model": "definitely-not-exist",
"messages": [{"role":"user","content":"hi"}]
}'
## ② 正常请求但观察流内结构
curl http://localhost:11434/api/generate -d '{"model":"gemma4","prompt":"hi"}'
第一条加了 -i 能看到状态行,第二条能看清 NDJSON 每行的结构。