Skip to content

fix(compression): prevent orphan sessions when state.db write fails (#33906) - #34048

Closed
zccyman wants to merge 1 commit into
NousResearch:mainfrom
atyou2happy:fix/33906-compression-orphan-sessions
Closed

fix(compression): prevent orphan sessions when state.db write fails (#33906)#34048
zccyman wants to merge 1 commit into
NousResearch:mainfrom
atyou2happy:fix/33906-compression-orphan-sessions

Conversation

@zccyman

@zccyman zccyman commented May 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Prevent orphan sessions when context compression's create_session() call fails (e.g. transient SQLite lock contention). The agent previously continued with a new session_id but no state.db row — producing an orphan session invisible in WebUI and /sessions.

Closes #33906

Problem

When context compression triggers a session rotation in conversation_compression.py:

  1. Old session is ended (end_session())
  2. New session_id is generated and immediately assigned to agent.session_id
  3. create_session() writes the new row to state.db

If step 3 fails (SQLite lock, disk I/O error), the agent continues with a session_id that has no state.db entry. The session is invisible in:

  • WebUI sidebar (/api/sessions returns only state.db rows)
  • /sessions CLI command
  • Session resume (/resume can't find it)
  • Usage tracking (token counts lost)

The entire try/except block only logs a warning — no rollback of the mutated session_id.

Solution

Three changes in agent/conversation_compression.py:

  1. Reorder assignment: generate new_session_id first, but only assign it to agent.session_id after create_session() succeeds
  2. Retry with backoff: 3 attempts for sqlite3.OperationalError (lock contention) with 0.1s × attempt delay
  3. Rollback on failure: restore agent.session_id to old value and reopen_session() the old session so the agent stays on a registered session

Edge case handled: if end_session() itself fails (before old_session_id is assigned), rollback uses locals().get() instead of direct reference to avoid UnboundLocalError.

Files Changed

File Change
agent/conversation_compression.py +46/-9: reorder, retry, rollback
tests/agent/test_compression_orphan_session.py +217: 6 new tests

Test Results

tests/agent/test_compression_orphan_session.py ...... (6 passed)
tests/agent/test_context_compressor.py .............. (129 passed)
tests/gateway/test_compress_*.py .................... (9 passed)
ruff check .......................................... All checks passed!

Design Decisions

  • Retry 3 times (not infinite): SQLite lock contention is transient; 3 attempts with backoff covers >99% of cases without blocking the agent
  • Rollback + reopen (not just skip): if we can't create the new session, we must keep the old one alive — end_session() already marked it as ended, so reopen_session() is required
  • locals().get() guard: avoids UnboundLocalError when end_session() fails before old_session_id = agent.session_id is reached

…ousResearch#33906)

When context compression triggers session rotation, the old session is
ended in state.db and a new one created. If create_session() fails
(e.g. transient SQLite lock contention), the agent previously continued
with the new session_id but no state.db row — producing an orphan
session invisible in WebUI and session list.

Changes:
- Reorder: generate new session_id first, but only assign it to
  agent.session_id AFTER create_session() succeeds
- Add 3-attempt retry with backoff for sqlite3.OperationalError
- On failure: rollback agent.session_id to old value and reopen the
  old session in state.db so the agent stays on a registered session
- Guard rollback with locals().get() to handle early failures before
  old_session_id is assigned

Tests: 6 new tests covering success path, retry path, rollback on
exhaustion, rollback on generic errors, early-failure edge case, and
session_id ordering invariant.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint labels May 28, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Merged via #49772 — your authorship is preserved as a co-author trailer on the squashed/rebased commit. This combined cluster fix incorporates the orphan-session rollback (failed child create_session) from this PR. Thanks for the contribution! #49772

@teknium1 teknium1 closed this Jun 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint 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.

Context compression creates orphan sessions missing from state.db

3 participants