错误码

请求被拒绝时,响应里带一个两维错误身份: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。

typeHTTP含义
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 也指向这里。

codeHTTP含义
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/ 下的一个类别页。