Mistral API 的报错大多不是模型能力问题,而是凭证、路径、参数、限流或网络。排查顺序应当是:先看 HTTP 状态码和错误类型,再看响应中的请求 ID 和最小复现,最后才调整提示词或更换模型。顺序反了,容易把配置错误误判成模型不行。

本文按 401、403、404、422、429、5xx 和超时逐项拆解,给出重试代码、并发治理、日志字段和支持工单清单。具体额度、错误文案与接口行为以 Mistral 官方文档和控制台为准。

说明:Mistral 是其权利人的商标。本文仅作技术讨论,错误码、限流口径和接口行为可能随版本调整,最终以官方文档与控制台为准。

一、先看状态码,不要先改提示词

状态或现象 常见含义 典型原因 处理顺序
401 未通过身份验证 Key 缺失、格式错误、已失效 先修凭证
403 没有权限 模型未开通、工作区角色不足、区域限制 查账户与权限
404 路径或模型不存在 Base URL 错误、路径重复、模型名下架 查地址和模型名
422 请求语义不合法 缺字段、类型错误、参数不支持 读错误详情改参数
429 触发限流或配额 并发突增、共享 Key、重试风暴 退避、降并发
5xx 上游服务异常 服务过载、网关错误、临时故障 有限重试、切换通道
超时 连接或读取超时 网络抖动、输出过长、代理空闲超时 分层定位

日志里至少记录时间、状态码、错误类型、模型名、耗时和请求 ID。不要记录完整 Key 和用户原文。

二、401 与 403:鉴权与权限

401 表示身份没有通过验证,和模型能力、余额通常无关。按下面顺序排查:

  • 请求头是否为 Authorization: Bearer <key>,而不是自定义字段或旧式鉴权。
  • Key 前后是否有空格、换行或多余引号,从聊天窗口复制最容易带进来。
  • 环境变量是否真的加载,可以只打印前缀确认,不要打印完整 Key。
  • Key 是否被删除、轮换或停用,测试环境是否误用了生产 Key。
  • Base URL 与 Key 是否属于同一平台,把 A 平台的 Key 打到 B 平台会直接 401。
  • 反向代理或 SDK 是否覆盖、丢弃了 Authorization 头。

403 是“身份已识别但没有权限”。常见原因是当前账户或工作区没有该模型的调用权限、角色权限不足、模型未对当前区域开放,或者请求打到了未开通的接口。先看控制台的模型列表和成员权限,再用同一把 Key 调一个已确认可用的模型做对照。

三、404 与 422:地址、模型名与参数

404 通常不是接口挂了,而是请求打到了不存在的路径或模型。常见原因包括 Base URL 写错、多写或少写 /v1、SDK 自动拼接路径后手写代码又拼了一次、模型名使用了已下架的旧版本,以及网关没有配置对应路由。先用完整地址发一个最小请求,确认返回体里的错误信息,再逐项对照控制台的模型清单。

422 表示请求格式正确但语义不合法,常见于缺少必填字段、字段类型不对、messages 为空、max_tokens 超出范围、传入了当前模型不支持的参数,或者 JSON 结构损坏。响应体通常会给出字段位置和原因,先读 detail 或 error 字段,按提示修改,不要盲目重试。

四、429:限流、并发与重试风暴

429 表示请求超过了速率、并发或配额限制,不等于余额不足。常见触发场景:

  • 多个服务共用一把 Key,互相挤占额度。
  • 批量任务在整点同时启动,形成流量脉冲。
  • 重试没有退避,越失败越发,形成重试风暴。
  • 长输出或流式请求占用连接较久,留给并发的空间变小。
  • 没有区分测试、预发和生产环境,测试流量打满生产配额。

处理时先看响应是否带有 Retry-After 等限流提示,有就按提示等待;没有就用指数退避加随机抖动。同时把并发降下来,给批量任务加队列和令牌桶,按模型、按 Key、按环境分别限额。不要把重试当成扩容,重试只能吸收短时抖动,不能解决长期容量不足。

五、5xx 与超时:上游、网络与流式

5xx 包括 500、502、503、504,可能是上游服务过载、网关转发失败或临时故障。先确认影响范围:是所有模型都失败,还是某个模型、某个区域、某条链路失败。短时 5xx 可以有限重试;持续 5xx 应降低并发、切换备用通道,并保留请求 ID 联系平台排查。

超时要分连接超时、读取超时和流式空闲超时。连接超时多与网络、DNS 或代理有关;读取超时常见于长输出、复杂推理和上游排队;流式请求还可能是代理的空闲超时切断了连接。客户端要显式设置连接和读取超时,流式场景要设置空闲超时和重连策略。对于有副作用的请求,超时后不要直接重发,先确认上游是否已经执行。

六、请求 ID 与日志:排查的依据

请求 ID 是跨团队排查的锚点。响应头或错误体中通常会带有请求标识,常见形式是 x-request-id。无论直连还是走网关,都要把它记录下来,并在日志中与业务单号关联。

建议日志至少包含:时间、请求 ID、状态码、错误类型、模型名、输入输出 token 数、耗时、重试次数、是否流式、上游通道。用户内容要脱敏或只保留摘要,Key 只记录前缀。没有请求 ID 的报错截图,很难让支持团队定位到具体请求。

七、重试与退避:哪些能重试,怎么重试

重试要满足三个条件:错误可恢复、请求可重复、重试有上限。401、403、404、422 不要重试,这些是配置或参数问题,重试只会浪费时间。429、5xx 和超时可以有上限地重试,并优先遵循 Retry-After。

下面的示例把可重试状态、指数退避、随机抖动和请求 ID 记录放在一起。生产环境还应加上熔断、指标上报和按业务幂等性判断是否重发。

import os
import random
import time

import requests

API_KEY = os.environ["MISTRAL_API_KEY"]
URL = "https://api.mistral.ai/v1/chat/completions"
RETRY_STATUS = {429, 500, 502, 503, 504}


def wait_seconds(resp, attempt):
    value = resp.headers.get("Retry-After") if resp is not None else None
    if value:
        try:
            return min(float(value), 60.0)
        except ValueError:
            pass
    return min(2 ** attempt + random.random(), 30.0)


def chat(payload, max_retries=4):
    last_error = None
    for attempt in range(max_retries + 1):
        try:
            resp = requests.post(
                URL,
                headers={
                    "Authorization": f"Bearer {API_KEY}",
                    "Content-Type": "application/json",
                },
                json=payload,
                timeout=(5, 60),  # 连接 5 秒,读取 60 秒
            )
        except requests.Timeout as exc:
            last_error = exc
            if attempt == max_retries:
                break
            time.sleep(wait_seconds(None, attempt))
            continue

        request_id = resp.headers.get("x-request-id", "unknown")
        if resp.status_code == 200:
            return resp.json()

        if resp.status_code in RETRY_STATUS:
            last_error = RuntimeError(
                f"HTTP {resp.status_code}, request_id={request_id}"
            )
            if attempt == max_retries:
                break
            time.sleep(wait_seconds(resp, attempt))
            continue

        # 401/403/404/422 重试没有意义,直接暴露配置或参数问题
        raise RuntimeError(
            f"HTTP {resp.status_code}, request_id={request_id}, "
            f"body={resp.text[:500]}"
        )

    raise RuntimeError(f"retry exhausted: {last_error}")

重试之外,还要做并发治理:为每个模型设置信号量,为批量任务设置队列,为不同环境使用不同的 Key,并为 429 比例设置告警。限流要按容量问题处理,而不是当成偶发错误。

八、支持工单清单

联系平台支持前,按下面清单整理信息,可以显著缩短排查时间:

  1. 发生时间与时间范围,注明时区,并说明是持续失败还是偶发。
  2. 完整请求 ID,以及对应的状态码和错误响应体,注意脱敏。
  3. 请求地址、模型名、是否流式、是否使用工具调用或结构化输出。
  4. 一条可复现的最小请求,去掉业务无关字段,保留必要参数。
  5. 影响范围:涉及多少用户、哪些地区、哪些网络环境,是否所有模型都失败。
  6. 近期变更:Key 是否轮换、模型是否升级、代理或网关配置是否调整。
  7. 已经做过的排查与结果,包括换 Key、换模型、换网络、降低并发的对比。

常见问题

401 换了新 Key 还是失败怎么办?

先确认新 Key 属于当前 Base URL 对应的平台,再检查环境变量是否真的加载、代理是否透传 Authorization 头。用最小请求分别打官方入口和网关入口,可以快速区分是 Key 问题还是链路问题。

429 是不是账户余额不足?

不是。429 表示请求超过了速率、并发或配额限制,余额不足通常会返回其他错误或在响应体中说明。先查并发、共享 Key 和重试策略,再查账户状态。

422 和 400 有什么区别?

两者都可能是参数问题,但 422 更强调请求格式正确、语义不合法,例如字段类型不对或缺少必填项。实际排查时都以响应体的字段提示为准,不要只凭状态码猜原因。

超时后能直接重发吗?

要看请求是否有副作用。纯查询可以有限重试;下单、扣款、发消息等操作要先确认上游是否已经执行,或者使用幂等键去重。超时只说明客户端没等到结果,不代表上游没有处理。

提工单前要准备什么?

准备时间范围、请求 ID、状态码、错误响应体、模型名、最小复现和影响范围。再说明近期变更和已经做过的排查,支持团队才能快速定位到具体链路。

下一步

先在中商起航 AI 网关创建测试 Key,把 401、422、429 和超时各演练一次,再接入生产监控。模型可用性与计费口径以模型价格为准。

相关阅读: