Codex压缩失败,出现“响应保护不可用”:问题出在网络搜索,而不是您的上下文

推理时代阅读约 8 分钟
Codex压缩失败,出现“响应保护不可用”:问题出在网络搜索,而不是您的上下文

自2026年10月8日起,长时间的Codex会话在尝试压缩时会立即崩溃。错误信息为 stream disconnected before completion: response protection is unavailable,重试无效,谈话无法继续。大多数报告涉及gpt-6.1-sol,但gpt-6-astra和gpt-5.6-sol也以相同方式失败。该问题出现在自托管代理后面,也出现在使用直接ChatGPT登录的官方Codex应用中。

简短的回答是:上下文并不太大,您的网络也不是问题。ChatGPT的Codex后端现在拒绝任何重放其历史中早期网络搜索的请求,而不声明网络搜索工具。Codex的压缩请求根本没有声明任何工具。因此,在会话早期进行一次网络搜索就足以使后续的每次压缩失败。

现在该怎么做:

  • 新会话:在后端或Codex更改之前,将 web_search = "disabled" 设置为禁用。
  • 卡住的会话:将工作移到一个新的会话中。旧会话无法压缩。
  • 如果您在Codex前面维护自己的网关:当历史中包含搜索时,添加网络搜索声明。代码如下。

本文的其余部分解释了如何发现触发器,哪些社区修复无效,以及如何拯救一个卡住的会话。

失败的表现

您将在Codex中看到以下信息:

stream disconnected before completion: response protection is unavailable
Error running remote compact task: stream disconnected before completion: stream closed before response.completed

第二条消息是通用版本。Codex并不总是显示上游错误,因此以“stream closed before response.completed”失败的压缩可能是同样的问题。Codex的本地日志中通常会有 Failed to run pre-sampling compact 的记录。

在其背后,上游发送两种信息之一。有时是带有此主体的HTTP 502,ChatGPT Plus用户在gpt-6.1-sol上也在OpenAI开发者论坛上发布过:

{"message": "response protection is unavailable", "type": "internal_error"}

其他时候是HTTP 200,其流以 response.failed 事件结束,带有 code: "upstream_error",且没有 response.completed。任何仅检查HTTP状态的请求都会错过第二种形式,并将其报告为提前结束的流。

模式在各处都是相同的:

  • 正常的交互仍然可以工作。只有压缩失败。
  • Codex大约重试五次,然后放弃。在一个网关的日志中,每次失败的尝试耗时2到13秒,并记录为零个令牌。
  • 恢复会话会遇到相同的压缩,因此会话保持卡住。
  • 新会话在遇到相同条件之前可以正常工作。

触发器:历史中的搜索,请求中没有搜索工具

Codex有一个内置的网络搜索工具。当模型使用它时,web_search_call 项会进入对话历史。每个后续请求都会将该历史发送回去。

正常的交互在 tools 中声明工具,因此上游接受重放的搜索。压缩请求则不同。Codex发送整个历史,tools: [],因为摘要不需要工具。这适用于Codex为自定义提供者运行的本地压缩,以及远程压缩v2。

大约在10月6日,ChatGPT Codex后端开始拒绝重放 web_search_call 但未声明 web_search 的请求。捕获原始请求的开发者缩小了范围。更改或删除搜索项的ID没有区别。仅声明一个功能工具仍然失败。声明 web_search 使相同的请求成功。

在使用官方未修改的codex-cli并使用ChatGPT账户登录时也出现相同的结果。包含三个搜索项的历史无法压缩。仅删除这些项的历史可以正常压缩。该线程中的第二位报告者捕获了一个包含一个 web_search_call 和 tools: [] 的压缩请求。添加 web_search 声明修复了它,删除搜索项也有效。

这解释了为什么看起来像是上下文大小的问题。压缩仅在长会话中运行,而长会话最有可能在某个时刻使用过搜索。网络搜索在Codex中也是默认开启的(默认模式为 "cached"),因此会话中可能包含用户从未请求过的搜索。

证据

至少有四个小组独立进行A/B测试,并得到了相同的结果。下面的行结合了在openai/codex跟踪器和几个开源网关项目的问题跟踪器中发布的测试。OpenAI尚未确认该规则或在任何线程中作出回应。

请求历史 声明的工具 结果
仅消息和推理 无 完成
包含功能调用输出 无 完成
包含一个web_search_call 无 失败
包含一个web_search_call 仅功能工具 失败
包含一个web_search_call web_search 完成
相同,删除搜索项 无 完成

这些测试排除了大小问题。一位测试者将自动压缩阈值设置为2000个令牌,使用 -c model_auto_compact_token_limit=2000。没有工具使用的会话可以正常压缩。进行过一次搜索的会话连续失败六次。另一位测试者发现,删除推理项没有帮助,而删除单个搜索项则有效。

在一次测试中,声明了 web_search 的版本在2.63秒内完成,并且没有新的搜索调用。声明工具不会使模型再次搜索。

社区尝试了什么,实际上有效的是什么

促使这篇文章的LINUX DO线程经过了大多数常见的猜测:

建议 有帮助吗? 原因
缩小上下文,提前压缩 没有 大小不是触发因素
通过IP连接,更改nginx 没有 错误来自上游
切换到WebSocket 不可靠 请求体无论如何都是相同的
直接登录ChatGPT 没有 官方登录也失败
新会话,交接上下文 临时解决方案 在搜索后再次失败
禁用网络搜索 是的,对于新会话 没有搜索,就没有触发
在请求中声明web_search 是的 满足检查条件

其中一些需要更多解释。

Nginx和IP。 超时和空闲连接可能导致其他“流断开”错误,但它们无法产生此消息。相关代理的维护者确认该消息不是由代理生成的;它来自上游提供者。如果消息存在,网络请求已成功传递并返回。

WebSocket。 有效的网关补丁必须同时覆盖WebSocket路径和HTTP,因为WebSocket请求携带相同的主体。一个在切换传输后“恢复”的会话很可能在其历史中没有搜索。

官方登录。 在openai/codex跟踪器上的报告包括桌面应用程序和直接使用ChatGPT账户登录的codex-cli,没有涉及代理。截至2026年10月10日,Codex 0.162.1或0.163.0 alpha版本均未提及修复,且问题没有维护者回应。

您现在可以做什么

为新会话禁用网络搜索

在 ~/.codex/config.toml 中关闭搜索:

web_search = "disabled"

Codex配置参考列出了四个值: disabled、 cached(默认值)、 indexed 和 live。使用 --yolo 或其他完全访问沙盒启动的会话默认设置为 live,因此请明确设置。

将此应用于新会话。旧会话的历史中已经有 web_search_call 项。禁用搜索后,正常的交互也停止声明工具,因此这些交互可能也会开始失败。这遵循上述规则,但尚未有人报告对此进行测试。

代价是Codex无法搜索网络。对于需要搜索的会话,请打开一个单独的短会话,或者让模型将发现写入文件,以便长会话读取。

拯救一个卡住的会话

在后端以这种方式运行时,您无法通过任何方式使卡住的会话压缩。为了保留工作:

  1. 保持卡住的会话不变。它的历史仍然保存在 ~/.codex/sessions/ 中。
  2. 启动一个新的会话,禁用网络搜索。
  3. 将其指向旧会话文件,或粘贴一个简短的交接:目标、已更改的文件、做出的决定和剩余的工作。
  4. 停止向旧会话发送提示。每次尝试都会重试压缩并再次失败。

如果您维护自己的网关

有效的修复遵循一个规则。如果 input 包含 web_search_call 且未声明任何 web_search* 工具,则添加一个。如果调用者未声明任何工具,则将 tool_choice 设置为 "none",以便工具无法运行。保持 input 不变。

def declare_replayed_web_search(body: dict) -> dict:
    """让上游接受在没有工具的请求中重放的web_search_call。"""
    items = body.get("input")
    if not isinstance(items, list):
        return body
    if not any(isinstance(i, dict) and i.get("type") == "web_search_call" for i in items):
        return body

    tools = body.get("tools") or []
    if any(isinstance(t, dict) and str(t.get("type", "")).startswith("web_search") for t in tools):
        return body

    caller_had_tools = bool(tools)
    # 仅缓存索引:声明存在是为了满足检查,而不是为了搜索。
    body["tools"] = tools + [{"type": "web_search", "external_web_access": False}]
    if not caller_had_tools:
        body["tool_choice"] = "none"
    return body

Responses Lite请求是一个例外。如果 web_search 位于顶层 tools 中,它将返回400。有效的补丁将其放在第一个 additional_tools 输入项中,并保持任何后续的 compaction_trigger 在最后。另一种选择是从压缩请求中剥离搜索项,但这样摘要将失去搜索找到的内容。

如果您不想依赖订阅后端

我们找到的每个报告都经过ChatGPT的订阅后端,这是Codex使用ChatGPT登录的端点。其规则没有文档记录,并且这一规则在没有通知的情况下发生了变化。

Codex还可以使用公共Responses API和API密钥。我们尚未在该路径上看到此错误的报告,但我们也没有在该路径上进行过重现,因此将其视为观察,而不是保证。要使用AIHubMix密钥设置Codex,请遵循Codex CLI教程:

model = "gpt-6.1-sol"
model_provider = "aihubmix"

[model_providers.aihubmix]
name = "AIHubMix"
base_url = "https://aihubmix.com/v1"
wire_api = "responses"
env_key = "AIHUBMIX_API_KEY"

API定价按令牌计算,而不是按订阅计算。费率在gpt-6.1-sol模型页面上。

检查清单

  • 错误文本包含“响应保护不可用”,或者压缩失败,出现“流在响应完成前关闭”。
  • 正常交互仍然有效,只有压缩失败。
  • 会话曾在某个时刻使用过网络搜索,可能没有被请求。
  • 新会话的web_search设置为禁用。
  • 卡住的工作已移至新会话,并附有交接说明。
  • 您维护的网关在历史中包含搜索时添加了网络搜索声明。
  • Nginx和代理网络设置保持不变。它们不是原因。

常见问题

Codex中的“响应保护不可用”是什么意思?
这是来自ChatGPT的Codex后端的错误,而不是Codex本身或您的代理。自2026年10月初以来,当请求重放早期的网络搜索但未声明网络搜索工具时,就会出现此错误,这正是压缩请求所做的。

我的上下文窗口太大了吗?
不。测试者在2000个令牌的压缩阈值下重现了此问题,而没有搜索的相同大小的会话可以正常压缩。它看起来与大小有关,仅仅是因为压缩仅在长会话中运行。

它会影响使用ChatGPT登录的官方Codex应用吗?
是的。桌面应用程序和codex-cli的用户在直接使用ChatGPT登录时报告了此问题,没有涉及代理。截至2026年10月10日,没有Codex版本提到修复。

我如何判断一个会话是否会遇到此问题?
如果会话在任何时候使用过网络搜索,则其下一个压缩很可能会失败。Codex将每次搜索记录为会话文件中的web_search_call项,位于.codex/sessions文件夹下。

禁用网络搜索会修复已经卡住的会话吗?
可能不会。旧历史仍然包含搜索,一旦禁用搜索,正常交互可能会停止声明工具并也失败。使用该设置用于新会话并将工作移过来。

切换到WebSocket或更改nginx有帮助吗?
没有。请求体在两种传输中都是相同的,错误来自上游,因此网络设置无法消除它。其他流错误可能来自超时,但不是这个错误。

当Codex使用API密钥而不是ChatGPT订阅时会发生此问题吗?
到目前为止,所有报告都涉及订阅后端。没有人报告在公共Responses API上发生此问题,尽管尚未直接测试。

继续阅读:GPT-6.1 Sol系列

来源