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 也以相同方式失敗。這個問題出現在自托管的代理後面,也出現在 官方 Codex 應用程序中,使用直接的 ChatGPT 登錄。

簡短的回答是:上下文並不過大,您的網路也不是問題。ChatGPT 的 Codex 後端現在拒絕任何重播其歷史中的早期網路搜尋的請求,而不聲明網路搜尋工具。Codex 的壓縮請求根本不聲明任何工具。因此,在會話早期進行的一次網路搜尋足以使每次後續的壓縮請求失敗。

當前應該採取的措施:

  • 新會話:設置 web_search = "disabled",直到後端或 Codex 發生變更。
  • 卡住的會話:將工作移至新的會話。舊的會話無法壓縮。
  • 如果您在 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,帶有這個主體,這是使用 gpt-6.1-sol 的 ChatGPT Plus 用戶在 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 跟蹤器上的報告包括桌面應用程序和 codex-cli,直接使用 ChatGPT 帳戶登錄,沒有涉及代理。截至 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 在 .codex/sessions 文件夾下的會話文件中記錄每次搜尋作為 web_search_call 項目。

禁用網路搜尋會修復已經卡住的會話嗎?
可能不會。舊的歷史仍然包含搜尋,並且一旦禁用搜尋,正常回合可能會停止聲明工具並也會失敗。對新會話使用此設置,並將工作移過去。

切換到 WebSocket 或更改 nginx 有幫助嗎?
不。無論使用哪種傳輸,請求主體都是相同的,錯誤來自上游,因此網路設置無法消除它。其他流錯誤可能來自超時,但這個錯誤不是。

當 Codex 使用 API 密鑰而不是 ChatGPT 訂閱時會發生此問題嗎?
到目前為止,所有報告都涉及訂閱後端。沒有人在公共 Responses API 上報告過此問題,儘管尚未直接測試。

繼續閱讀:GPT-6.1 Sol 系列

來源