Skip to content

fix(tui): end_session on finalize to prevent ghost sessions in /resume (#18269)#18299

Closed
Bartok9 wants to merge 1 commit into
NousResearch:mainfrom
Bartok9:fix/18269-tui-ghost-sessions
Closed

fix(tui): end_session on finalize to prevent ghost sessions in /resume (#18269)#18299
Bartok9 wants to merge 1 commit into
NousResearch:mainfrom
Bartok9:fix/18269-tui-ghost-sessions

Conversation

@Bartok9

@Bartok9 Bartok9 commented May 1, 2026

Copy link
Copy Markdown
Contributor

Problem

TUI sessions were eagerly persisted to state.db via db.create_session() inside _start_agent_build()/_build(), but db.end_session() was never called when a TUI session closed. All three close paths converge on _finalize_session():

Path Code
Normal quit / /quit session.close RPC → _finalize_session(session)
Ctrl+C atexit_shutdown_sessions()_finalize_session(session)
/new (new session within TUI) Eventually also goes through finalize

_finalize_session() committed memory and fired hooks but never called db.end_session(). Every session row therefore accumulated with ended_at = NULL and appeared as a resumable entry in /resume.

On one user's install: 24 out of 52 TUI sessions (46%) were ghost rows with message_count = 0.

Fix

Add db.end_session(key, end_reason) at the end of _finalize_session():

key = session.get("session_key")
if key:
    db = _get_db()
    if db is not None:
        db.end_session(key, end_reason)

This mirrors how the CLI handles session lifecycle — cli.py already calls end_session() on /new and quit. A default end_reason="tui_close" is added so the audit trail matches CLI conventions.

No risk to existing sessions

db.end_session() is a no-op when ended_at is already set (see hermes_state.py:547):

UPDATE sessions SET ended_at = ?, end_reason = ?
WHERE id = ? AND ended_at IS NULL   -- ← no-op for already-ended sessions

So sessions that are ended through other paths (e.g. compression, /branch) won't be double-ended.

Verification

Closes #18269

NousResearch#18269)

TUI sessions were persisted to the DB via db.create_session() inside
_start_agent_build/_build() but db.end_session() was never called when
the TUI session closed.  All three close paths — session.close RPC,
Ctrl+C (atexit _shutdown_sessions), and /quit — called _finalize_session
which committed memory and fired hooks but never marked the session as
ended.  The result: every session row accumulated with ended_at=NULL,
appearing as resumable entries in /resume.

Fix: add db.end_session(key, end_reason) to _finalize_session().  This is
the correct mirror of how CLI handles session lifecycle (cli.py calls
end_session on /new and on quit).  _finalize_session already receives the
session dict which carries session_key; we simply call end_session on that
key at the end.

An end_reason argument (default 'tui_close') is added so callers can pass
a more specific reason when available.  Internally _shutdown_sessions and
session.close both use the default; future callers (e.g. session.resume
ending the old session) can pass a distinct reason for audit clarity.

Closes NousResearch#18269
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels May 1, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #18283 — same fix calling db.end_session() in _finalize_session() to prevent ghost rows. Both close #18269.

@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #18283

@alt-glitch

Copy link
Copy Markdown
Collaborator

Superseded by #18370 which includes this fix (adapted with credit — see tui_gateway/server.py _finalize_session change). Thank you @Bartok9!

@Bartok9

Bartok9 commented May 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @alt-glitch — confirmed superseded by #18370 which includes this fix with credit. Closing to keep the board clean.

@Bartok9 Bartok9 closed this May 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) 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.

[Bug]: TUI eagerly persists empty sessions to DB — ghost sessions clutter /resume

2 participants