Skip to content

fix(context_compressor): treat httpcore streaming premature-close as transient (salvage #22653)#22846

Merged
teknium1 merged 1 commit into
mainfrom
salvage/pr-22653
May 10, 2026
Merged

fix(context_compressor): treat httpcore streaming premature-close as transient (salvage #22653)#22846
teknium1 merged 1 commit into
mainfrom
salvage/pr-22653

Conversation

@teknium1

@teknium1 teknium1 commented May 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Salvage of #22653httpcore.RemoteProtocolError from streaming premature-close is now classified as a transient/connection error in the auxiliary client and routed to the short-cooldown / aux→main fallback path in context_compressor.

Root cause

agent/auxiliary_client.py::_is_connection_error substring list covered classic socket errors but missed httpcore's "incomplete chunked read", "peer closed connection without sending complete message body", "response ended prematurely", "unexpected eof". agent/context_compressor.py::_generate_summary's except block didn't even call _is_connection_error — only _is_model_not_found, _is_timeout, _is_json_decode. So mid-stream connection drops fell into the unknown-error path with the long 60s cooldown.

Changes (contributor commit)

  • agent/auxiliary_client.py: extend _is_connection_error substring list + add class-name fallbacks ("remoteprotocolerror", "localprotocolerror"). Wrap from openai import APIConnectionError, APITimeoutError in try/except so the function works in venvs without openai installed.
  • agent/context_compressor.py::_generate_summary: classify _is_streaming_closed alongside existing transient classes, route to the same aux→main fallback + 30s short-cooldown path.

Validation

  • The PR's regression tests cover all four meaningful branches (aux→main fallback, short-cooldown when on main, negative-case unclassified retains 60s).

Closes #18458 via salvage.

… error

Problem:
When a provider or proxy drops a streaming response mid-flight (httpcore
raises RemoteProtocolError: "incomplete chunked read", "peer closed
connection", "response ended prematurely", etc.), _generate_summary
would not classify it as a transient error.  Instead of retrying on the
main model, it entered the generic 60-second cooldown, leaving context
growing unbounded until the cooldown expired.  Issue #18458.

Root cause:
_is_connection_error in auxiliary_client.py did not match httpcore's
streaming premature-close error substrings.  context_compressor.py's
_generate_summary except block never called _is_connection_error, so
those errors fell through to the 60-second generic cooldown rather than
triggering the retry-on-main fallback path used for timeouts.

Fix:
1. auxiliary_client.py — extend _is_connection_error keyword list with:
   "incomplete chunked read", "peer closed connection",
   "response ended prematurely", "unexpected eof",
   "remoteprotocolerror", "localprotocolerror".
   Also guard the `from openai import ...` with try/except ImportError
   so the function works in environments without the openai package.
2. context_compressor.py — import _is_connection_error and call it in
   _generate_summary's except block as _is_streaming_closed.  Include
   _is_streaming_closed in the fallback-to-main condition (alongside
   _is_model_not_found, _is_timeout, _is_json_decode) and use the
   shorter 30s transient cooldown for streaming-closed errors.

Tests:
4 new regression tests in TestStreamingClosedFallback:
- test_incomplete_chunked_read_falls_back_to_main
- test_peer_closed_connection_falls_back_to_main
- test_streaming_closed_on_main_uses_short_cooldown  (stash-verified)
- test_non_streaming_unknown_error_still_uses_long_cooldown

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions

github-actions Bot commented May 9, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: salvage/pr-22653 vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 7953 on HEAD, 7953 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 4201 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent loop, run_agent.py, prompt builder labels May 9, 2026
@teknium1 teknium1 merged commit 35f773c into main May 10, 2026
16 of 18 checks passed
@teknium1 teknium1 deleted the salvage/pr-22653 branch May 10, 2026 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve context compression retry/fallback for incomplete chunked reads

3 participants