Skip to content

fix(gateway): break compression-exhaustion infinite loop and auto-reset session - #10063

Merged
teknium1 merged 1 commit into
mainfrom
hermes/fix-9893-compression-exhaustion
Apr 15, 2026
Merged

teknium1 merged 1 commit into
mainfrom
hermes/fix-9893-compression-exhaustion

Conversation

@teknium1

Copy link
Copy Markdown
Collaborator

Summary

Fixes #9893 — gateway becomes unresponsive when context compression is exhausted in long-running group chat sessions.

Root Cause (two-layer bug)

Layer 1: When compression fails after max attempts, run_conversation() returns {completed: False, partial: True} but was missing the "failed" flag. The gateway's agent_failed_early guard only checks for "failed".

Layer 2: Even if "failed" were set, the guard was dead code. _run_agent_blocking always converts error results to a final_response (line 8622: "⚠️ {error}"), so the guard's and not agent_result.get("final_response") clause was always False.

Result: The oversized session gets persisted to the transcript after every failed compression attempt. The next message loads the same oversized history, hits the same compression failure, and loops. The user sees repeated "compacting context..." messages until the gateway dies.

Changes

run_agent.py

  • Add "failed": True and "compression_exhausted": True to all 5 compression-exhaustion return paths (413 payload too large, context length exceeded, cannot compress further)

gateway/run.py

  • _run_agent_blocking: Forward "failed" and "compression_exhausted" flags from the agent result to the caller
  • _handle_message_with_agent: Fix agent_failed_early to use bool(agent_result.get("failed")) — removing the broken and not final_response clause that made it dead code
  • Auto-reset: When compression_exhausted is True, automatically reset the session (reset_session + cache eviction + model override clear) so the next message starts fresh. Appends a user-visible notice explaining the auto-reset.

Tests

  • Updated TestGatewaySkipsPersistenceOnFailure to match the new guard logic
  • Added TestCompressionExhaustedFlag class with 2 tests

Test Results

  • tests/run_agent/test_1630_context_overflow_loop.py — 16/16 passed
  • tests/run_agent/test_compression_feasibility.py — 12/12 passed
  • tests/gateway/ — 2879 passed (10 failures + 10 errors are pre-existing, unrelated)

…et session (#9893)

When compression fails after max attempts, the agent returns
{completed: False, partial: True} but was missing the 'failed' flag.
The gateway's agent_failed_early guard checked for 'failed' AND
'not final_response', but _run_agent_blocking always converts errors
to final_response — making the guard dead code.  This caused the
oversized session to persist, creating an infinite fail loop where
every subsequent message hits the same compression failure.

Changes:
- run_agent.py: add 'failed: True' and 'compression_exhausted: True'
  to all 5 compression-exhaustion return paths
- gateway/run.py (_run_agent_blocking): forward 'failed' and
  'compression_exhausted' flags through to the caller
- gateway/run.py (_handle_message_with_agent): fix agent_failed_early
  to check bool(failed) without the broken 'not final_response' clause;
  auto-reset the session when compression is exhausted so the next
  message starts fresh
- Update tests to match new guard logic and add
  TestCompressionExhaustedFlag test class

Closes #9893
@teknium1
teknium1 merged commit c5688e7 into main Apr 15, 2026
6 of 7 checks passed
@teknium1
teknium1 deleted the hermes/fix-9893-compression-exhaustion branch April 15, 2026 04:18
teknium1 pushed a commit that referenced this pull request Jun 13, 2026
…tion auto-reset

After compression exhaustion the auto-reset created a fresh session but
discarded reset_session()'s return value and left the Telegram topic
binding pointing at the oversized compressed child. The next inbound
message in that topic healed the binding forward and switch_session'd the
freshly-reset lane back onto the bloated transcript, re-triggering
compression exhaustion in a loop with a new session id each time.

Capture the fresh entry and re-sync the topic binding to it so the next
message starts clean. No-op on non-topic lanes.

Regression of the #9893/#10063 auto-reset fix.

Fixes #35809
AIalliAI pushed a commit to AIalliAI/Hermes that referenced this pull request Jun 14, 2026
…tion auto-reset

After compression exhaustion the auto-reset created a fresh session but
discarded reset_session()'s return value and left the Telegram topic
binding pointing at the oversized compressed child. The next inbound
message in that topic healed the binding forward and switch_session'd the
freshly-reset lane back onto the bloated transcript, re-triggering
compression exhaustion in a loop with a new session id each time.

Capture the fresh entry and re-sync the topic binding to it so the next
message starts clean. No-op on non-topic lanes.

Regression of the NousResearch#9893/NousResearch#10063 auto-reset fix.

Fixes NousResearch#35809
T02200059 pushed a commit to T02200059/hermes-agent that referenced this pull request Jun 18, 2026
…tion auto-reset

After compression exhaustion the auto-reset created a fresh session but
discarded reset_session()'s return value and left the Telegram topic
binding pointing at the oversized compressed child. The next inbound
message in that topic healed the binding forward and switch_session'd the
freshly-reset lane back onto the bloated transcript, re-triggering
compression exhaustion in a loop with a new session id each time.

Capture the fresh entry and re-sync the topic binding to it so the next
message starts clean. No-op on non-topic lanes.

Regression of the NousResearch#9893/NousResearch#10063 auto-reset fix.

Fixes NousResearch#35809
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…tion auto-reset

After compression exhaustion the auto-reset created a fresh session but
discarded reset_session()'s return value and left the Telegram topic
binding pointing at the oversized compressed child. The next inbound
message in that topic healed the binding forward and switch_session'd the
freshly-reset lane back onto the bloated transcript, re-triggering
compression exhaustion in a loop with a new session id each time.

Capture the fresh entry and re-sync the topic binding to it so the next
message starts clean. No-op on non-topic lanes.

Regression of the NousResearch#9893/NousResearch#10063 auto-reset fix.

Fixes NousResearch#35809
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
…tion auto-reset

After compression exhaustion the auto-reset created a fresh session but
discarded reset_session()'s return value and left the Telegram topic
binding pointing at the oversized compressed child. The next inbound
message in that topic healed the binding forward and switch_session'd the
freshly-reset lane back onto the bloated transcript, re-triggering
compression exhaustion in a loop with a new session id each time.

Capture the fresh entry and re-sync the topic binding to it so the next
message starts clean. No-op on non-topic lanes.

Regression of the NousResearch#9893/NousResearch#10063 auto-reset fix.

Fixes NousResearch#35809
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…tion auto-reset

After compression exhaustion the auto-reset created a fresh session but
discarded reset_session()'s return value and left the Telegram topic
binding pointing at the oversized compressed child. The next inbound
message in that topic healed the binding forward and switch_session'd the
freshly-reset lane back onto the bloated transcript, re-triggering
compression exhaustion in a loop with a new session id each time.

Capture the fresh entry and re-sync the topic binding to it so the next
message starts clean. No-op on non-topic lanes.

Regression of the NousResearch#9893/NousResearch#10063 auto-reset fix.

Fixes NousResearch#35809
donbowman pushed a commit to donbowman/hermes-agent that referenced this pull request Jul 13, 2026
…tion auto-reset

After compression exhaustion the auto-reset created a fresh session but
discarded reset_session()'s return value and left the Telegram topic
binding pointing at the oversized compressed child. The next inbound
message in that topic healed the binding forward and switch_session'd the
freshly-reset lane back onto the bloated transcript, re-triggering
compression exhaustion in a loop with a new session id each time.

Capture the fresh entry and re-sync the topic binding to it so the next
message starts clean. No-op on non-topic lanes.

Regression of the NousResearch#9893/NousResearch#10063 auto-reset fix.

Fixes NousResearch#35809
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…tion auto-reset

After compression exhaustion the auto-reset created a fresh session but
discarded reset_session()'s return value and left the Telegram topic
binding pointing at the oversized compressed child. The next inbound
message in that topic healed the binding forward and switch_session'd the
freshly-reset lane back onto the bloated transcript, re-triggering
compression exhaustion in a loop with a new session id each time.

Capture the fresh entry and re-sync the topic binding to it so the next
message starts clean. No-op on non-topic lanes.

Regression of the NousResearch#9893/NousResearch#10063 auto-reset fix.

Fixes NousResearch#35809
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…tion auto-reset

After compression exhaustion the auto-reset created a fresh session but
discarded reset_session()'s return value and left the Telegram topic
binding pointing at the oversized compressed child. The next inbound
message in that topic healed the binding forward and switch_session'd the
freshly-reset lane back onto the bloated transcript, re-triggering
compression exhaustion in a loop with a new session id each time.

Capture the fresh entry and re-sync the topic binding to it so the next
message starts clean. No-op on non-topic lanes.

Regression of the NousResearch#9893/NousResearch#10063 auto-reset fix.

Fixes NousResearch#35809
melon-xf added a commit to melon-xf/hermes-agent that referenced this pull request Sep 3, 2026
…tion auto-reset

After compression exhaustion the auto-reset created a fresh session but
discarded reset_session()'s return value and left the Telegram topic
binding pointing at the oversized compressed child. The next inbound
message in that topic healed the binding forward and switch_session'd the
freshly-reset lane back onto the bloated transcript, re-triggering
compression exhaustion in a loop with a new session id each time.

Capture the fresh entry and re-sync the topic binding to it so the next
message starts clean. No-op on non-topic lanes.

Regression of the NousResearch#9893/NousResearch#10063 auto-reset fix.

Fixes NousResearch#35809
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gateway becomes unresponsive when context compression is exhausted in long-running group chat sessions

1 participant