跳转至

02 · Provider 异常映射:跨 provider 矩阵与已知不一致

本文聚焦 litellm/litellm_core_utils/exception_mapping_utils.py(2465 行)这一个文件——它是 LiteLLM 把上游错误转成 01 目录里那些 LiteLLM 异常类的唯一枢纽。

读完应该能回答:

  • 调 GPT-5 失败抛的 BadRequestError 跟调 Claude 失败抛的 BadRequestError,背后是同一段代码吗?
  • 上游 502,LiteLLM 一定抛 BadGatewayError 吗?
  • 我要接入一个新 provider,应该按哪个 provider 抄?
  • 为什么我看到的 cloudflare 错总是 APIConnectionError

1. 两个事实先定调

事实 1:18 个分支,实际服务 60+ provider

文件里实际只有 18 个 if/elif custom_llm_provider == "xxx" 大分支。但实际接入的 provider 远不止 18 个:

# constants.py:711-770
openai_compatible_providers: List = [
    "anyscale", "groq", "nvidia_nim", "cerebras", "baseten", "sambanova",
    "ai21_chat", "ai21", "volcengine", "codestral", "deepseek", "deepinfra",
    "perplexity", "xinference", "xai", "zai", "together_ai", "fireworks_ai",
    "empower", "friendliai", "azure_ai", "github", "litellm_proxy",
    "hosted_vllm", "llamafile", "lm_studio", "galadriel", "github_copilot",
    "chatgpt", "novita", "meta_llama", "publicai", "synthetic", "apertis",
    "nano-gpt", "poe", "chutes", "featherless_ai", "nscale", "nebius",
    "dashscope", "moonshot", "v0", "helicone", "morph", "lambda_ai",
    "hyperbolic", "vercel_ai_gateway", "aiml",
    # ...共 54 个
]

exception_mapping_utils.py:355-361:

if (
    custom_llm_provider == "openai"
    or custom_llm_provider == "text-completion-openai"
    or custom_llm_provider == "custom_openai"
    or custom_llm_provider in litellm.openai_compatible_providers   # ← 54 个
    or custom_llm_provider == "mistral"
):

共 58 个 provider 共用同一段 openai 映射行 356-617)。所以你看到 moonshot / deepseek / groq / dashscope 报错时,走的实际是 OpenAI 分支——上游说 500 在这一段就映射成 InternalServerError,跟真正的 OpenAI 一视同仁。

剩下 17 个独立分支:anthropicreplicatebedrocksagemakervertex_aicloudflarecoherehuggingfaceai21(独立)、nlp_cloudtogether_ai(独立)、aleph_alphaollamavllmazureopenrouter + 全局兜底。

⚠️ ai21together_ai 出现了两次——既在 openai_compatible_providers 里又有独立分支。映射代码按 elif 链顺序匹配,所以 ai21_chat 走 openai 分支,但 ai21 同时命中 openai 分支和独立分支——前者赢行 356-617 在前,1673 行的 elif custom_llm_provider == "ai21" 永远不会进入)。这是 dead codetogether_ai 同理(1839)。如果你 grep 看 together_ai/ai21 独立分支,它根本不会执行——所有 together_ai 错都按 openai 规则映射。

事实 2:双判定结构(关键字 + status_code)

绝大多数 provider 分支结构都是:

elif custom_llm_provider == "xxx":
    # ① 先按 error_str 关键字判定(pre-status-code)
    if "context limit" in error_str:
        raise ContextWindowExceededError(...)
    elif "content policy" in error_str:
        raise ContentPolicyViolationError(...)
    ...

    # ② 再按 status_code 判定
    if hasattr(original_exception, "status_code"):
        if original_exception.status_code == 400:
            raise BadRequestError(...)
        elif original_exception.status_code == 401:
            raise AuthenticationError(...)
        ...

关键字判定优先级高于 status_code。这是导致反直觉映射的根因之一——同一个 502 错误,关键字命中"context limit"就当 400 处理,关键字都不命中才轮到 502 自己的分支。


2. 全局路径:3 个不走 provider 分支的入口

在进入 provider if/elif 链之前,有三条全局快速通道直接出口:

2.1 LITELLM_EXCEPTION_TYPES 已包装直通(行 240-244

if any(
    isinstance(original_exception, exc_type)
    for exc_type in litellm.LITELLM_EXCEPTION_TYPES
):
    return original_exception

如果异常已经是 LiteLLM 异常(被下层映射过),直接返回。保护双重映射:例如 Router 重试时上一次拿到的已经是 RateLimitError,再过一次 exception_type 不会被错误包装成 APIConnectionError

2.2 全局 Timeout 字符串嗅探(行 329-344

if (
    "Request Timeout Error" in error_str
    or "Request timed out" in error_str
    or "Timed out generating response" in error_str
    or "The read operation timed out" in error_str
):
    raise Timeout(...)

任何 provider 的 error string 含上述 4 个子串之一就立即转 Timeout,跳过整个 provider 分支链。

⚠️ 暗坑:如果上游本来返了一个 500 但消息恰好包含 "Request timed out"(如 nginx 504 错误页内容),会被映射成 Timeout(status_code=408)不是 504/500。这会改变 Router 的 cooldown 和 retry 路径——按 408 走 cooldown 第一关白名单(✅),按 408 走 _should_retry(✅),但实际上上游可能是永久故障。

2.3 litellm_proxy 反查(行 346-354

if custom_llm_provider == "litellm_proxy":
    extract_and_raise_litellm_exception(
        response=getattr(original_exception, "response", None),
        error_str=error_str,
        model=model,
        custom_llm_provider=custom_llm_provider,
    )

调用 extract_and_raise_litellm_exception行 194-229),用正则 litellm\.\w+Error 从错误消息里反查类名再 raise

这是 LiteLLM 套娃 LiteLLM 时的特殊路径——上游 proxy 已经把异常名前缀写进 message(litellm.RateLimitError: ...),下游 proxy 拿到后用正则提取类名重建异常对象,避免二次包装。

⚠️ 三个注意: 1. 这个函数走完会 raise——直接跳出 exception_type,下面的 openai 分支不会执行。 2. 但 litellm_proxy 也在 openai_compatible_providers 里(constants.py:734),如果反查没命中(消息不含 litellm.XxxError 前缀),会 fall-through 到 openai 分支。 3. 如果上游 proxy 用了新版本引入的异常类(如假设的 litellm.QuotaExceededError),下游 proxy 没这个类,getattr(litellm, "QuotaExceededError", None) 返 None,继续 fall-through而非抛错——错误名信息会被丢失。


3. status_code × provider 矩阵(精简版)

完整 18 × 13 矩阵太宽不便阅读。这里按"标准化程度"分 3 档(S / M / L),每档列出该档常见的 status_code 处理情况。

S 档:处理 6 个以上 status_code 的"完整 provider"

Provider 400 401 403 404 408 422 429 500 502 503 504 其它
openai 系 (58 个) BR Au NF TO BR RL IS BG SU TO API
anthropic BR Au NF TO BR RL IS BG SU TO
azure BR Au TO BR RL BG SU TO API
vertex_ai BR Au PD NF TO RL IS BG SU
bedrock BR Au PD NF TO BR RL SU SU TO
sagemaker BR Au NF TO BR RL SU SU TO
openrouter BR Au NF TO BR RL SU TO API

M 档:4-5 个 status_code

Provider 400 401 403 404 408 422 429 500 502 503 504 其它
replicate BR Au TO UE RL SU API
cohere BR TO BR (*CCE→RL) IS API/IS
huggingface BR Au TO RL SU API
nlp_cloud BR Au Au BR RL API API SU API

L 档:< 4 个 status_code 的"裸 provider"——大量 fall-through 到全局兜底

Provider 处理的 status_code 其它行为
cloudflare 仅按字符串:"Authentication error"→Au, "must have required property"→BR 其它全部走全局兜底 → APIConnectionError(⚠️ 见 §4.1)
ai21(独立分支) dead code(见 §1
together_ai(独立分支) dead code(同上)
aleph_alpha 401, 400, 429, 500 缺 404/408/422/502/503/504 → 全局兜底
ollama 按字符串:连接错/路径错/超时 缺所有 status_code 处理 → 全局兜底
vllm 仅 status_code == 0 → APIConnectionError行 2047 缺所有其它 status → 全局兜底
litellm_proxy 不走 status_code,全靠反查 message 前缀 命中不了就 fall-through

图例: - BR = BadRequestError,Au = AuthenticationError,PD = PermissionDeniedError,NF = NotFoundError - TO = Timeout,RL = RateLimitError,UE = UnprocessableEntityError - IS = InternalServerError,BG = BadGatewayError,SU = ServiceUnavailableError - API = APIError*CCE = CohereConnectionError 类名嗅探 - "—" = 该 status_code 在此 provider 分支里没有处理(→ 走全局兜底 / 上层逻辑) - 粗体 = 跟"OpenAI 风格"不同,详见 §4

完整行号见底部 §6 行号附录


4. 已知不一致点

跨 provider 比较时,这 7 处是真的会改变 Router 行为的不一致——不是代码风格差异,是异常类选错会让 cooldown / retry / 客户端 status_code 全错。

4.1 ⚠️ cloudflare:几乎裸奔,全部 fall-through 到 APIConnectionError

行 1480-1496

elif custom_llm_provider == "cloudflare":
    if "Authentication error" in error_str:
        raise AuthenticationError(...)
    if "must have required property" in error_str:
        raise BadRequestError(...)
    # ← 没了。这就是全部。

没有 status_code 分支。如果 cloudflare 返 500/502/503,error_str 不含上面两个关键字,会一路 fall-through 到全局兜底行 2361-2383)→ APIConnectionError

后果: - 客户端看到的 status_code 是 500(APIConnectionError 硬编码),不管上游真的是 502/503/其它 - Router cooldown 被 ignored_strings = ["APIConnectionError"] 跳过(cooldown_handlers.py:57-63),故障 deployment 不会被冷却 - Router 也不会 retry(_should_retry(500) 是 True,但 APIConnectionError 本身没 response.status_code

如果你 prod 在用 cloudflare workers ai,这点要重视。建议监控里把 APIConnectionError + cloudflare 单独画一条。

4.2 ⚠️ together_ai 独立分支有死循环 bug(同时是 dead code)

行 1908-1947

if hasattr(original_exception, "status_code"):
    if original_exception.status_code == 408: raise Timeout(...)
    elif 422: raise BadRequestError(...)
    elif 429: raise RateLimitError(...)
    elif 524: raise Timeout(...)
    # ← 401/403/500/503 没处理,且没有 else 兜底
else:
    raise APIError(
        status_code=original_exception.status_code,   # ← AttributeError!
        ...
    )

两个问题:

  1. else 分支保证进来时没有 status_code 属性,但第一行就访问 original_exception.status_code → AttributeError。这是真 bug。
  2. if hasattr ... 块缺 401/403/500/503 处理——status_code 是这些值时静默 fall-through 到全局兜底 → APIConnectionError

⚠️ 但整段是 dead code§1 事实 1):together_aiopenai_compatible_providers 里,永远走 openai 分支。所以这个 bug 不会真的爆——但留着是历史包袱。

4.3 cohere 500 用 InternalServerError,replicate/bedrock/sagemaker 500 用 ServiceUnavailableError

cohere 1554 vs replicate 819 vs bedrock 1059 vs sagemaker 1175

Provider 上游真返 500 抛哪个 LiteLLM 异常
openai 系 / anthropic / vertex_ai / cohere 500 InternalServerError(status_code=500)
replicate / bedrock / sagemaker / aleph_alpha 500 ServiceUnavailableError(status_code=503

后果: - 客户端看到的 status_code 不同(500 vs 503) - _should_retry 都返 True(两者都是 5xx),所以 retry 行为一样 - Cooldown 都进白名单,所以 cooldown 行为一样 - 但监控/告警按 status_code 分组的会割裂——同样的故障在两个面板上

合理选择:500 应该用 InternalServerError。bedrock/sagemaker 那条线可能是历史习惯——把 5xx 都当"暂时不可用"。

4.4 nlp_cloud 500/503 都用 APIError,504/520 用 ServiceUnavailableError

行 1807-1829

elif original_exception.status_code == 500 or status_code == 503:
    raise APIError(status_code=..., ...)   # ← 不是 InternalServerError/SU
elif status_code == 504 or status_code == 520:
    raise ServiceUnavailableError(...)     # ← 不是 Timeout(其他 provider 504→TO)

对比

status nlp_cloud 其他 provider
500 APIError(500) InternalServerError(500)
503 APIError(503) ServiceUnavailableError(503)
504 ServiceUnavailableError(503)(注意 status_code 被替换) Timeout(408)Timeout(504)
520 ServiceUnavailableError(503) 没处理(落全局兜底)

最严重:504 在其他 provider 是 Timeout,nlp_cloud 变成 ServiceUnavailableError——RetryPolicy.TimeoutErrorRetries 配置对 nlp_cloud 504 完全无效。

4.5 vertex_ai 字符串 "403" 和 status_code 403 抛不同异常

行 1319-1333 vs 行 1411

elif "403" in error_str:
    raise BadRequestError(...)   # ← 字符串路径
...
elif original_exception.status_code == 403:
    raise PermissionDeniedError(...)   # ← status_code 路径

字符串路径优先§1 事实 2),所以多数情况下 vertex 403 抛 BadRequestError

后果:客户端拿到 400 而不是 403。_should_retry(400)=False_should_retry(403)=False,都不 retry;cooldown 都不进白名单——所以实际行为没变。但 status_code 错了,监控/客户端逻辑可能误判。

实际是想要 PermissionDenied 的:上游真的 403(key 没开通 vertex 配额)就是 PermissionDeniedError;但字符串里出现 "403" 三个字符就被截胡。

4.6 sagemaker:credentials 错被映射为 BadRequestError

行 1142-1149

if "Unable to locate credentials" in error_str:
    raise BadRequestError(...)

对比 bedrock 行 1008-1019

if (
    "Unable to locate credentials" in error_str
    or "The security token included in the request is invalid"
    in error_str
):
    raise AuthenticationError(...)

同样的 AWS 错误消息,bedrock 映射为 AuthenticationError(401),sagemaker 映射为 BadRequestError(400)。后果不一样:401 进 cooldown 白名单 + 路径 1.4 立即冷却;400 既不 retry 也不 cooldown。

4.7 vllm:status_code == 0 → APIConnectionError(设计正确,但与文档不直观)

行 2043-2052

elif custom_llm_provider == "vllm":
    if hasattr(original_exception, "status_code"):
        if original_exception.status_code == 0:
            raise APIConnectionError(...)

这是对的——vllm client(litellm/llms/vllm/completion/handler.py)有约定:本地连不上时把 status_code 设为 0。这里转 APIConnectionError 语义正确(本地网络问题)。

vllm 分支只有这一条——其它任何 status(500、502、503)都 fall-through 到全局兜底 → APIConnectionError(也是网络层错),Router 永远不冷却 vllm deployment。如果 vllm 真的 OOM 返 500,你的 LiteLLM 会反复打过去。


5. 全局兜底:ensure generic errors always return APIConnectionError

行 2350-2410

if "BadRequestError.__init__() missing 1 required positional argument: 'param'" in str(original_exception):
    # 处理 openai-python sdk 的一个 edge-case bug
    raise BadRequestError(...)
else:
    # ensure generic errors always return APIConnectionError
    if hasattr(original_exception, "request"):
        raise APIConnectionError(
            message="{} - {}".format(exception_provider, error_str),
            ...
        )
    else:
        raise APIConnectionError(
            message="{}\n{}".format(str(original_exception), traceback.format_exc()),
            ...
        )

这里是最后一道防线——所有 provider 分支都不命中时,统一抛 APIConnectionError

⚠️ 设计意图 vs 实际后果: - 设计意图:LiteLLM 不希望 client 看到原始 httpx.HTTPError 之类的异常,必须包装成 OpenAI 兼容格式。APIConnectionError 是个"通用未知错"的兜底类。 - 实际后果:因为这个兜底,任何 provider 分支不处理的 status_code 都会被映射成 APIConnectionError。结合 cooldown 白名单的字符串跳过逻辑——provider 分支不完整 = Router 在这个 provider 上的健康判断失效

这就是为什么 cloudflare(§4.1)和 vllm(§4.7)那么危险——它们的 provider 分支太短了。

最最后兜底行 2400-2410:上面 try 块抛了任何异常(包括映射逻辑自己崩了),catch 后再走一次 LITELLM_EXCEPTION_TYPES 检查;都不匹配就再抛一个 APIConnectionError,拿 traceback.format_exc() 拼到 message 里。这是兜底的兜底。


6. message-based 关键字判定速查

按 provider 列出所有靠错误字符串关键字(不靠 status_code)决定异常类型的位置。

openai 系(含 58 个 provider,行 387-502

关键字 抛出 行号
ExceptionCheckers.is_error_str_rate_limit() (含 "rate limit"/"429"/"service tier capacity exceeded" 等) RateLimitError 387
is_error_str_context_window_exceeded() (含 "exceed context limit" 等 8 个子串) ContextWindowExceededError 395
"invalid_request_error" + "model_not_found" NotFoundError 404
"A timeout occurred" Timeout 416
内容审核三元组(content_policy_violation / Invalid prompt ... violating our usage policy / request was rejected as a result of the safety system ContentPolicyViolationError 424
"invalid_request_error" && NOT "Incorrect API key provided" BadRequestError 446
"Web server is returning an unknown error" / "The server had an error processing your request" InternalServerError 460
"Request too large" RateLimitError ⚠️(不是 BR) 469
"The api_key client option must be set ..." AuthenticationError 479
"Mistral API raised a streaming error" APIError 490

anthropic(行 621-651

关键字 抛出
"prompt is too long" / "prompt: length" ContextWindowExceededError
"overloaded_error" / "Overloaded" InternalServerError
"Invalid API Key" AuthenticationError
"content filtering policy" ContentPolicyViolationError
"Client error '400 Bad Request'" BadRequestError

vertex_ai(行 1262-1385

关键字 抛出
"Vertex AI API has not been used in project" / "Unable to find your project" BadRequestError
"400 Request payload size exceeds" ContextWindowExceededError
is_error_str_context_window_exceeded() ContextWindowExceededError
"None Unknown Error." / "Content has no parts." InternalServerError
"API key not valid." AuthenticationError
"403" BadRequestError ⚠️(不是 PD,见 §4.5
"The response was blocked." / "Output blocked by content filtering policy" ContentPolicyViolationError
429 系列 5 个关键字("429 Quota exceeded" / "Quota exceeded for" / "Resource exhausted" / "IndexError: list index out of range" ⚠️ / "429 Unable to submit ... temporarily out of capacity" RateLimitError
"500 Internal Server Error" / "The model is overloaded." InternalServerError

⚠️ "IndexError: list index out of range" 映射到 RateLimitError 很可疑——这看起来像是 Python 代码 bug 信息,跟限流没关系。可能是上游某个特定路径 quota 耗尽时 SDK 抛 IndexError,作者经验性映射。核对前不要依赖

bedrock(行 968-1049

关键字 抛出
6 个 context window 关键字("too many tokens" / "expected maxLength:" / "Input is too long" / "prompt is too long" / "prompt: length: 1.." / "Too many input tokens" ContextWindowExceededError
"Conversation blocks and tool result blocks cannot be provided in the same turn." BadRequestError
"Malformed input request" / "A conversation must start with a user message." BadRequestError
"Unable to locate credentials" / "The security token included in the request is invalid" AuthenticationError
"AccessDeniedException" PermissionDeniedError
"throttlingException" / "ThrottlingException" RateLimitError
"Connect timeout on endpoint URL" / "timed out" Timeout
"Could not process image" InternalServerError

其它 provider 关键字简表

Provider 关键字数 备注
sagemaker 4 "Unable to locate credentials" 映射成 BadRequestError§4.6)⚠️
cloudflare 2 整个分支只有这两条(§4.1
cohere 7 含类名嗅探 "CohereConnectionError" in exception_type
huggingface 3
nlp_cloud 6+(JSON detail 解析)
together_ai 多(JSON error_response 解析) dead code
aleph_alpha 2
ollama 4(dict.get("error") 字符串嗅探)
azure 6+ body["error"]["inner_error"]["code"] == "ResponsibleAIPolicyViolation" 这种深结构判定

7. 历史 bug:2026-05-29 commit 2bee019 修了什么

commit 2bee019 TCLOUD-11688 fix 订阅模式故障转移 把 vertex_ai 的 502 映射从 APIConnectionError 改成 BadGatewayError

                     if original_exception.status_code == 502:
                         exception_mapping_worked = True
-                        raise APIConnectionError(
-                            message=f"{custom_llm_provider.capitalize()}Exception - {error_str}",
+                        raise BadGatewayError(
+                            message=f"BadGatewayError: {custom_llm_provider.capitalize()} - {error_str}",
                             llm_provider=custom_llm_provider,
                             model=model,
                         )

修复前:vertex 上游 502 → APIConnectionError(status_code=500) → Router 不冷却 → 反复打坏实例。 修复后:vertex 上游 502 → BadGatewayError(status_code=502) → cooldown 白名单进 → 路径 1.3 失败率高时冷却 → fallback 切走。

→ 这就是 §4.1 cloudflare / §4.7 vllm 当前还在的 bug 类型——历史包袱按 provider 逐个清。


8. 实操:要接入一个新 provider 该按谁抄?

按"完整度"由高到低:

抄哪个 优点 适用
openai 系行 356-617 11 个 status_code + 10 个关键字判定,最完整;走 openai_compatible_providers 一键复用 你的 provider 是 OpenAI 兼容 API
anthropic行 618-732 7 个 status_code 含 502/503/504;message 判定有内容审核 类似 Anthropic 的 messages 格式
vertex_ai行 1262-1479 字符串判定丰富;新 commit 已修 502 坑;但 403 字符串路径有§4.5的坑 Google 系
azure行 2053-2253 内容审核走 body["error"]["inner_error"]["code"] 结构化判定;完整 status_code 处理 Azure 衍生

不该抄: - ❌ cloudflarevllmaleph_alpha 这种短分支——会继承 fall-through 到 APIConnectionError 的问题 - ❌ nlp_cloud——status_code 500/503/504 用错了类 - ❌ replicate/bedrock/sagemaker 的 500→ServiceUnavailableError——客户端 status_code 会错 - ❌ together_ai 独立分支——它本身是 dead code

接入新 provider 的最小 checklist

elif custom_llm_provider == "your_provider":
    # 1. 提取 message
    message = get_error_message(error_obj=original_exception)
    if message is None:
        message = getattr(original_exception, "message", str(original_exception))

    # 2. 关键字优先(可选)—— 上游字符串能给的语义先抓
    if "context length" in error_str:
        raise ContextWindowExceededError(message=..., model=model, llm_provider="your_provider")
    if "content policy" in error_str:
        raise ContentPolicyViolationError(...)

    # 3. status_code 全量覆盖
    if hasattr(original_exception, "status_code"):
        sc = original_exception.status_code
        if sc == 400: raise BadRequestError(...)
        elif sc == 401: raise AuthenticationError(...)
        elif sc == 403: raise PermissionDeniedError(...)
        elif sc == 404: raise NotFoundError(...)
        elif sc == 408: raise Timeout(...)
        elif sc == 422: raise UnprocessableEntityError(...)
        elif sc == 429: raise RateLimitError(...)
        elif sc == 500: raise InternalServerError(...)
        elif sc == 502: raise BadGatewayError(...)           # ← 别图省事用 APIConnectionError
        elif sc == 503: raise ServiceUnavailableError(...)
        elif sc == 504: raise Timeout(exception_status_code=504, ...)
        else: raise APIError(status_code=sc, ...)            # ← 不要让它 fall-through 到全局兜底

第 3 步那个 else: raise APIError(...) 是关键——它保证非标准 status_code 也带正确的 status_code 出去,不会变 APIConnectionError


9. 行号附录:全部 raise 位置

主要 status_code → 异常类 → 行号速查(按 status_code 然后 provider 排序):

400 BadRequestError

openai 507 / anthropic 672 / replicate 780 / bedrock 1080 / sagemaker 1196 / vertex_ai 1389 / cloudflare 1491 / cohere 1541 / huggingface 1635 / nlp_cloud 1769 / aleph_alpha 1981 / azure 2164 / openrouter 2260

401 AuthenticationError

openai 516 / anthropic 662 / replicate 769 / bedrock 1072 / sagemaker 1188 / vertex_ai 1404 / huggingface 1627 / ai21 1694 / nlp_cloud 1780 / aleph_alpha 1974 / azure 2174 / openrouter 2269

403 PermissionDeniedError

vertex_ai 1411(仅此一处用了正确的类)

404 NotFoundError

openai 525 / anthropic 679 / bedrock 1088 / sagemaker 1204 / vertex_ai 1425 / openrouter 2278

408 Timeout

openai 534 / anthropic 686 / replicate 796 / bedrock 1096 / sagemaker 1212 / vertex_ai 1432 / cohere 1549 / huggingface 1643 / ai21 1702 / together_ai 1911 / azure 2183 / openrouter 2287

422 UnprocessableEntityError

replicate 788(唯一用 UE 的——其他都映射为 BadRequestError)

429 RateLimitError

openai 552 / anthropic 693 / replicate 811 / bedrock 1113 / sagemaker 1232 / vertex_ai 1440 / huggingface 1650 / ai21 1717 / nlp_cloud 1801 / together_ai 1926 / aleph_alpha 1989 / azure 2200 / openrouter 2304

500 InternalServerError / ServiceUnavailableError 混用

openai 561 IS / anthropic 703 IS / vertex_ai 1455 IS / cohere 1556 IS(§4.3) replicate 819 SU ⚠️ / bedrock 1059 SU ⚠️ / sagemaker 1175 SU ⚠️ / aleph_alpha 1997 SU ⚠️ nlp_cloud 1812 APIError ⚠️(§4.4

502 BadGatewayError

openai 570 / anthropic 711 / vertex_ai 1468(2bee019 修复) / azure 2209

503 ServiceUnavailableError

openai 579 / anthropic 719 / bedrock 1122 / sagemaker 1241 / vertex_ai 1475 / huggingface 1658 / azure 2218 / openrouter 2313 nlp_cloud 1812 用了 APIError ⚠️

504 Timeout / 其它

openai 588 TO / anthropic 727 TO / bedrock 1131 TO / sagemaker 1250 TO / azure 2227 TO / openrouter 2322 TO nlp_cloud 1824 ServiceUnavailableError ⚠️(§4.4

APIConnectionError 出现位置

openai fallback 608 / vllm status==0 2047(§4.7)/ azure "Connection error" 2154 / azure no-status fallback 2248 / openrouter no-status fallback 2341 / 全局兜底 2367 + 2374 + 2404


下一步