错误码
请求被拒绝时,响应里带一个两维错误身份:type 是客户端分支用的粗类别,同时决定 HTTP 状态码;code 指明是哪条规则没过;param 定位到出错的字段路径。
错误包络
type 与 message 一定返回;code 与 param 在能定位时才携带。OpenAI 生态的 SDK 会把 error.message 原样读进异常。接入示例见快速开始。
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Invalid API key provided."
},
"request_id": "req-…"
}
类型(type)
七个值,一一映射 HTTP 状态码;客户端按它决定重试还是放弃。上游对请求体本身的拒绝(HTTP 400/422)按 invalid_request_error 透传,message 是上游原文;上游限流保留 429,上游超时映射 504,其余上游故障是 502。
| type | HTTP | 含义 |
|---|---|---|
invalid_request_error |
400 | 请求体没通过校验,或参数不合法 |
authentication_error |
401 | 凭证不通过:key 不存在、从未签发或已吊销 |
permission_error |
403 | 凭证有效但被授权面拒绝:模型未授权、余额为负、访问受限 |
not_found_error |
404 | 引用不存在:模型没有可用路由、引用的 response 已失效、主机未声明 |
request_too_large |
413 | 请求体超出缓冲上限 |
rate_limit_error |
429 | 触发限流,响应头带 Retry-After |
api_error |
502 / 504 | 上游失败或超时 |
错误码(code)
一条规则一个码。表里每个码都链到本页的分码说明,也各自是一个锚点:model-r.com/docs/errors# 加上码值直达,错误包络未来的 doc_url 也指向这里。
| code | HTTP | 含义 |
|---|---|---|
missing_required_parameter |
400 | 必填字段缺失或为空 |
invalid_type |
400 | 字段类型不对 |
invalid_value |
400 | 类型正确但取值不可用 |
enum_value |
400 | 封闭枚举取值超界 |
integer_below_min_value |
400 | 整数低于下限 |
number_out_of_range |
400 | 数值超出协议固定的范围 |
array_empty |
400 | 必填数组为空 |
array_above_max_items |
400 | 数组超过上限 |
array_item_invalid |
400 | 数组元素形状不对 |
mutually_exclusive |
400 | 互斥字段同时出现 |
reserved_value |
400 | 侵入保留命名空间 |
unsupported_parameter |
400 | 不支持的参数表面 |
malformed_json |
400 | 请求体不是 JSON 对象 |
previous_response_not_found |
404 | 引用的存储响应不存在 |
invalid_api_key |
401 | key 无效 |
alias_not_granted |
403 | key 没有该模型的授权 |
undeclared_host |
404 | 主机未声明或已停用 |
insufficient_balance |
403 | 钱包余额为负 |
model_not_found |
404 | 模型名没有可用路由 |
access_restricted |
403 | 准入规则限制 |
rate_limit_exceeded |
429 | 超出限流窗口 |
分码说明
每个码按参考平台的写法给出四件事:它能触发的具体情况、会触发它的请求、该请求实际返回的包络、处理办法。包络里的 message 是网关返回的原文;param 给出的路径(例如 messages[2].content[1].text)定位到出错的那一项。
missing_required_parameter
HTTP 400(invalid_request_error)
- 三个接口的必填顶层字段缺失:
model;chat 与 messages 的messages;responses 创建形态的input - 消息内的必填字段缺失:
messages[i].role、messages[i].content、文本块的text;文本字段传空字符串同样按缺失处理 - 工具与输入条目内的必填字段缺失:函数声明的
name、responses 输入条目的type、function_call 条目的call_id、function_call_output 条目的output
会触发它的请求
{
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
]
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "missing_required_parameter",
"param": "model",
"message": "Missing 'model'"
},
"request_id": "req-…"
}
按 param 指出的字段路径补上该字段后重发。文本字段需要占位时给出非空文本,空字符串不视为已提供。
invalid_type
HTTP 400(invalid_request_error)
- 数值与整数字段传了字符串或小数:
temperature与top_p要求数字,max_tokens、seed、max_tool_calls要求整数 - 布尔字段
stream、parallel_tool_calls传了非布尔值 - 数组字段
messages、tools传了非数组值;对象字段thinking、output_config、reasoning传了非对象值
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
],
"max_tokens": "8"
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "invalid_type",
"param": "max_tokens",
"message": "'max_tokens' must be an integer"
},
"request_id": "req-…"
}
按 message 声明的类型改写字段取值后重发。类型错误在校验层拒绝,不会被静默转换成错误取值继续执行。
invalid_value
HTTP 400(invalid_request_error)
- messages 接口的
thinking.type为空字符串:'thinking.type' must be a non-empty string thinking.budget_tokens搭在非官方思考档位 key 上:"enabled"之外的非空 type 是二相思考 key,不接受预算字段- responses 接口输入条目的
type不在认识范围内:Unknown input item type '…'
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
],
"thinking": {
"type": "deep-research",
"budget_tokens": 8000
}
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "invalid_value",
"param": "thinking.budget_tokens",
"message": "thinking.budget_tokens requires thinking.type 'enabled'"
},
"request_id": "req-…"
}
message 点名不可用的取值,param 给出字段路径,按两者改写后重发。
enum_value
HTTP 400(invalid_request_error)
- chat 的
messages[i].role取system、developer、user、assistant、tool之外的值 - messages 的
role取user、assistant之外的值 - chat 的
tool_choice字符串形态取auto、none、required之外的值 - 思考档位字段(
reasoning_effort、reasoning.effort、output_config.effort)不会触发此码:档位之外的取值是二相思考 key,按设计放行
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "bot",
"content": "帮我写一个快速排序的单元测试"
}
]
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "enum_value",
"param": "messages[0].role",
"message": "'role' must be one of: system, developer, user, assistant, tool"
},
"request_id": "req-…"
}
message 列出该字段的全部合法取值,改回其中之一后重发。
integer_below_min_value
HTTP 400(invalid_request_error)
- 三个接口的
max_tool_calls传 0 或负数。下限 1 在边界强制执行:0 会允许执行循环零次工具调用,静默改变行为
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
],
"max_tool_calls": 0
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "integer_below_min_value",
"param": "max_tool_calls",
"message": "'max_tool_calls' must be an integer ≥ 1"
},
"request_id": "req-…"
}
改成不小于 1 的整数后重发。上限随模型与路由变化,不在边界检查,由上游报告。
number_out_of_range
HTTP 400(invalid_request_error)
- chat 的
temperature超出 [0, 2] - chat 的
top_p超出 [0, 1] - 上下界是协议常量,所有合规后端一致;随模型变化的数值上限(例如各模型自己的
max_tokens上限)不在此处检查
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
],
"temperature": 2.5
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "number_out_of_range",
"param": "temperature",
"message": "'temperature' must be between 0.0 and 2.0"
},
"request_id": "req-…"
}
改回范围内后重发。
array_empty
HTTP 400(invalid_request_error)
- chat 与 messages 的
messages传空数组:空输入对补全请求没有意义 - responses 的生成轮
input传空数组;预热轮(generate: false)携带空input是合法形状,不触发
会触发它的请求
{
"model": "your-model",
"messages": []
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "array_empty",
"param": "messages",
"message": "'messages' must not be empty"
},
"request_id": "req-…"
}
至少提供一条消息(responses 接口至少一个输入条目)后重发。
array_above_max_items
HTTP 400(invalid_request_error)
- chat 的
stop超过官方上限 4 个停止序列:多出的条目会在读取时被丢弃,因此整包拒绝
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
],
"stop": [
"END",
"STOP",
"###",
"总结",
"完"
]
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "array_above_max_items",
"param": "stop",
"message": "'stop' must hold at most 4 items"
},
"request_id": "req-…"
}
删到 4 个以内后重发。
array_item_invalid
HTTP 400(invalid_request_error)
stop(chat 与 responses)或stop_sequences(messages)里有非字符串元素:'stop[1]' must be a string- chat 的
stop里有空字符串:Stop sequences must be non-empty strings
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
],
"stop": [
"END",
5
]
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "array_item_invalid",
"param": "stop[1]",
"message": "'stop[1]' must be a string"
},
"request_id": "req-…"
}
param 已定位到出错的下标,只修该元素后重发,其余元素无需改动。
mutually_exclusive
HTTP 400(invalid_request_error)
- messages 接口同时声明
output_config.effort与thinking:两者是同一思考控制面的两代形态,同时声明没有唯一意图,网关拒绝而不是任选其一
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
],
"thinking": {
"type": "enabled",
"budget_tokens": 8000
},
"output_config": {
"effort": "high"
}
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "mutually_exclusive",
"param": "output_config.effort",
"message": "'output_config.effort' and 'thinking' are mutually exclusive; declare one"
},
"request_id": "req-…"
}
只保留一个控制面后重发。
reserved_value
HTTP 400(invalid_request_error)
- 三个接口声明的工具名以
__开头:该前缀保留给托管函数在传输层的改写命名,客户端占用会与托管函数名冲突
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "__search",
"description": "在知识库里检索文档"
}
}
]
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "reserved_value",
"param": "tools[0].function.name",
"message": "Tool name must not use the reserved prefix '__': __search"
},
"request_id": "req-…"
}
换一个不以 __ 开头的工具名后重发。
unsupported_parameter
HTTP 400(invalid_request_error)
- messages 的顶层
mcp_servers - responses 的
tools里type: "mcp"的工具 - messages 的
tools里mcp_toolset条目 - 三者返回同一句 message。这些参数被明确拒绝而不是忽略:接受它们会把服务端的函数定义权移入请求
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
],
"mcp_servers": [
{
"type": "url",
"url": "https://mcp.example.net/sse"
}
]
}
返回
{
"error": {
"type": "invalid_request_error",
"code": "unsupported_parameter",
"param": "mcp_servers",
"message": "Client-declarable MCP tools are not supported; hosted tools are defined server-side (docs/unsupported-features.md)"
},
"request_id": "req-…"
}
移除该参数后重发;需要外部能力时改用控制台配置的托管函数。
malformed_json
HTTP 400(invalid_request_error)
- 请求体不是可解析的 JSON
- 请求体解析出的根不是 JSON 对象,例如直接把
messages数组当作请求体发送 - 请求体为空
- 此码不携带
param:错误无法定位到单个字段
会触发它的请求
curl https://api.model-r.com/v1/chat/completions \
-H "Authorization: Bearer mr-…" \
-H "Content-Type: application/json" \
-d '[{"role": "user", "content": "帮我写一个快速排序的单元测试"}]'
返回
{
"error": {
"type": "invalid_request_error",
"code": "malformed_json",
"message": "Request body must be a JSON object"
},
"request_id": "req-…"
}
检查请求体的编码与 Content-Type: application/json 后重发。示例里的请求体是一个数组,合法请求体必须是一个 JSON 对象。
previous_response_not_found
HTTP 404(not_found_error)
- responses 续聊的压缩形态里
previous_response_id指向的响应链已过期、被逐出或从未在本部署创建 - 部署没有发布响应链存储:任何引用都返回 404,message 直接给出替代做法
会触发它的请求
{
"model": "your-model",
"previous_response_id": "resp_9f8e7d6c"
}
返回
{
"error": {
"type": "not_found_error",
"code": "previous_response_not_found",
"param": "previous_response_id",
"message": "The referenced conversation is not held by this deployment (it expired, was evicted, or was created elsewhere)"
},
"request_id": "req-…"
}
不再引用历史响应,把需要的上下文放回 input 重发。请求本身合法,是引用的留存失效。
invalid_api_key
HTTP 401(authentication_error)
- key 不存在、从未签发或已被吊销
- Authorization 头不是
Bearer方案,或没有携带凭证 - 以上情况返回同一句 message,不区分具体原因:报错不泄露任何 key 的存在性信息
会触发它的请求
curl https://api.model-r.com/v1/chat/completions \
-H "Authorization: Bearer mr-not-a-valid-key" \
-H "Content-Type: application/json" \
-d '{"model": "your-model", "messages": [{"role": "user", "content": "帮我写一个快速排序的单元测试"}]}'
返回
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Invalid API key provided."
},
"request_id": "req-…"
}
到门户核对 key 的拼写与有效期;已被吊销的 key 在门户重新签发。请求体与此码无关,无需改动。
alias_not_granted
HTTP 403(permission_error)
- key 有效且已通过认证,但其授权模型列表(非空时)不含本次请求的
model;授权列表为空表示不限模型,不触发
会触发它的请求
{
"model": "your-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
]
}
返回
{
"error": {
"type": "permission_error",
"code": "alias_not_granted",
"message": "The presented key was not granted the requested alias."
},
"request_id": "req-…"
}
在门户为该 key 补充该模型的授权,或改用该 key 已授权的模型。重新认证不改变该结果。
undeclared_host
HTTP 404(not_found_error)
- 请求的 Host 不在接入端点表内;已停用的声明按未声明处理
- 请求没有声明 Host
- 此码与 key、请求体均无关:拒绝发生在认证与解析之前
会触发它的请求
curl https://api.model-r.com/v1/chat/completions \
-H "Host: api.wrong-host.example" \
-H "Authorization: Bearer mr-…" \
-d '{"model": "your-model", "messages": [{"role": "user", "content": "帮我写一个快速排序的单元测试"}]}'
返回
{
"error": {
"type": "not_found_error",
"code": "undeclared_host",
"message": "No access endpoint is declared for host 'api.wrong-host.example'."
},
"request_id": "req-…"
}
使用快速开始给出的接入地址 api.model-r.com 后重发。
insufficient_balance
HTTP 403(permission_error)
- key 所属账户的钱包余额为负。检查发生在请求执行前,不是结算时才发现
- message 不回显余额数字:余额在门户可见
返回
{
"error": {
"type": "permission_error",
"code": "insufficient_balance",
"message": "The account's balance is negative; recharge to resume requests."
},
"request_id": "req-…"
}
到门户充值后重发原请求,请求无需改动。
model_not_found
HTTP 404(not_found_error)
model字段的名字在路由表内没有条目:可能是拼写错误,也可能是该模型尚未开放路由
会触发它的请求
{
"model": "no-such-model",
"messages": [
{
"role": "user",
"content": "帮我写一个快速排序的单元测试"
}
]
}
返回
{
"error": {
"type": "not_found_error",
"code": "model_not_found",
"param": "model",
"message": "No route is configured for model 'no-such-model'"
},
"request_id": "req-…"
}
核对模型名拼写;在门户确认该 key 可用的模型列表后重发。
access_restricted
HTTP 403(permission_error)
- 挂载的准入规则拒绝了请求,具体是谁限制了什么写在
message里 - 本环境当前的具体来源:账户被运营方停用
返回
{
"error": {
"type": "permission_error",
"code": "access_restricted",
"message": "This account has been disabled by the operator; contact the operator to resume requests."
},
"request_id": "req-…"
}
按 message 的指引处理。重新认证不改变该结果,只有解除限制本身才能放行。
rate_limit_exceeded
HTTP 429(rate_limit_error)
- 认证账户的某个限流窗口在本请求到达时已超出预算,请求在触及上游之前被拒绝
- 窗口名、额度与秒数取自该账户配置的限流窗口
- 响应头额外携带
Retry-After(秒数)与X-RateLimit-*
返回
{
"error": {
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded for window 'per-minute' (60 requests per 60 seconds); wait the Retry-After delay and retry"
},
"request_id": "req-…"
}
等待 Retry-After 给出的秒数后重试原请求。重新认证与修改请求均不改变该结果。
限流响应头
rate_limit_exceeded 的响应除包络外,还带 Retry-After(秒数)与标准的 X-RateLimit-* 头。按 Retry-After 退避重试。
控制台接口的错误
管理与门户的 REST 接口报错是 RFC 9457 problem+json,type 字段就是类别地址,指向 https://model-r.com/problems/ 下的一个类别页。