`ssl.SSLError` during a request is no longer retried since 3.14.1

这个报错通常出现在 OpenAI Python SDK 从 3.14.1 起读取响应时抛出 ssl.SSLError 的场景,请求不会重试,而是直接把裸 ssl.SSLError 抛给调用方。优先排查 SDK 版本是否落在 3.14.1 到 3.20.0 之前的区间。

快速结论:这个报错通常出现在 OpenAI Python SDK 从 3.14.1 起读取响应时抛出 ssl.SSLError 的场景,请求不会重试,而是直接把裸 ssl.SSLError 抛给调用方。优先排查 SDK 版本是否落在 3.14.1 到 3.20.0 之前的区间。

适用环境:Issue 中确认的环境为 Python 3.13.7、macOS;openai 3.19.2(复现失败)、openai 3.13.0(可重试);httpx2 / httpcore2 2.12.0,也见于 2.13.1;使用 pydantic-ai 2.51(失败)与 2.49(重试)对接 OpenRouter,并发的流式 chat completions。未提及 CUDA、显卡。

最快修复方案:升级到 openai v3.20.0。Issue 评论中维护者确认 v3.20.0 加入了 shim 修复该回归,随后提交者确认 3.20.0 已解决;在此之前可临时将 openai 固定(pin)到 3.13.0。

注意事项:v3.20.0 的修复被维护者描述为等待上游修复期间的 shim,属于临时方案;真正的重试逻辑修复(在 request_exceptions() 中包含 ssl.SSLError)来自社区分支提案。若你在 3.20.0 上仍看到裸 ssl.SSLError,说明可能不是同一回归,需另行排查。

问题场景

通过 OpenAI Python SDK 发起请求,并使用异步客户端读取响应时触发。典型场景是 pydantic-ai 经 OpenRouter 并发调用流式 chat completions,约 10 个进程并行,偶发地在读取响应头阶段出现 TLS 错误。相同代码在 3.13 / 3.14.0 会重试并成功,在 3.14.1 及之后首次失败即抛出。

报错原文

File ".../httpcore2/_async/http11.py", line 167, in _receive_response_headers
File ".../httpcore2/_backends/anyio.py", line 37, in read
File ".../anyio/streams/tls.py", line 254, in receive
ssl.SSLError: [SSL: SSLV3_ALERT_BAD_RECORD_MAC] ssl/tls alert bad record mac (_ssl.c:2657)

# 最小复现输出对比
openai 3.13.0: APIConnectionError after 3 attempt(s)
openai 3.14.0: APIConnectionError after 3 attempt(s)
openai 3.14.1: SSLError after 1 attempt(s)
openai 3.19.2: SSLError after 1 attempt(s)

原因分析

Issue 作者定位为 #3867(“preserve application errors”)的副作用:该改动把重试范围收窄到 httpx2.TimeoutException / httpx2.RequestError,而 httpcore2 并未把所有 TLS 错误映射为 httpx2 异常——AnyIOStream.read() 只映射 anyio 的 BrokenResourceError / ClosedResourceError / EndOfStream,因此读取中途抛出的 ssl.SSLError 会以未映射形式冒泡,被当作应用错误直接抛出,不再重试、也不再包装为 APIConnectionError。

环境排查

  • 确认 openai 版本:3.14.1 至 3.20.0 之前属于受影响区间;3.13.0 / 3.14.0 行为正常(会重试并抛 APIConnectionError)。
  • 确认 Python 版本:Issue 报告为 Python 3.13.7。
  • 确认 httpx2 / httpcore2 版本:2.12.0,也在 2.13.1 上出现。
  • 确认上层调用链:pydantic-ai 2.51 表现为失败,2.49 表现为重试。
  • 确认是否使用异步客户端与并发流式请求(复现条件之一)。
  • 确认操作系统:macOS。

解决步骤

  1. 先把 openai 升级到 v3.20.0,该版本包含针对此回归的兼容 shim。
  2. 如果当前不能升级,临时将 openai 固定到 3.13.0,可恢复 TLS 错误的重试行为。
  3. 如果你想自行修复源码,可参考社区分支的提案:在 request_exceptions() 中把 ssl.SSLError 一并纳入可重试的异常集合(该分支为 rwinkelman/openai-python 的 fix/retry-sslerror-and-auth-typo,可优先尝试,但属提案性质,未经上游合入)。
  4. 升级或固定版本后,用最小复现脚本验证:在不访问网络的情况下注入一个抛出 ssl.SSLError 的 transport,观察重试次数与最终异常类型。

验证方法

运行最小复现脚本,若输出为 APIConnectionError after 3 attempt(s)(max_retries=2 时共 3 次尝试),说明已恢复重试与错误包装;若仍输出 SSLError after 1 attempt(s),说明修复未生效。真实场景中可观察并发流式请求下 TLS 错误是否被自动重试,以及失败回复数量是否下降。

参考来源

openai/openai-python #3969

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 26472

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注