Skip to content

fix(cli): initialize session_id before OpenViking orphan commit - #31493

Closed
Ramadas108 wants to merge 2 commits into
NousResearch:mainfrom
Ramadas108:pr/startup-session-order
Closed

fix(cli): initialize session_id before OpenViking orphan commit#31493
Ramadas108 wants to merge 2 commits into
NousResearch:mainfrom
Ramadas108:pr/startup-session-order

Conversation

@Ramadas108

Copy link
Copy Markdown

This fixes a startup crash introduced when OpenViking orphan-session recovery was called before HermesCLI.session_id was assigned.

On a fresh CLI startup, _commit_orphaned_openviking_sessions() can reference self.session_id before the constructor has created it, causing:

AttributeError: 'HermesCLI' object has no attribute 'session_id'

The fix moves the orphan commit call after session_id assignment, initializes session_id="" as a safe default at the top of __init__, and wraps the call in try/except so that an OpenViking failure never blocks CLI startup. A defensive getattr(self, "session_id", "") fallback is also used as an additional guard against future reordering.

Changes:

  1. cli.py — safe default initialization, deferred call ordering, non-fatal error handling
  2. tests/cli/test_cli_startup.py — regression smoke tests proving HermesCLI() can initialize without AttributeError and survives a simulated orphan-commit crash

This keeps orphan-session recovery behavior unchanged, but prevents it from blocking CLI startup.

Hermes Agent added 2 commits May 24, 2026 12:10
…cess takes over

Adds _commit_orphaned_openviking_sessions() called from HermesCLI.__init__
that discovers sessions left behind by killed or crashed Hermes processes
(ended_at=NULL or end_reason='new_session' without commit) and sends
POST /api/v1/sessions/{sid}/commit to OpenViking to finalize memory
extraction.

Fixes two scenarios:
- Process A killed (SIGKILL/terminal close) while session active —
  session never receives final commit
- Process B starts via /new but crashes before OpenViking HTTP response
  returns — session committed in state.db but not in OpenViking

Testing: 4 orphaned sessions recovered from state.db, 346 abandoned
CLI sessions closed with orphaned_restart end_reason.
The _commit_orphaned_openviking_sessions() call in HermesCLI.__init__
referenced self.session_id before it was assigned, causing
AttributeError on startup.

Fix: initialize self.session_id= as a safe default at the top of
the constructor, move the orphan commit to after the formal session_id
assignment, wrap it in try/except so an OpenViking failure never blocks
startup, and use getattr(self, session_id, ) as an additional
defensive fallback.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins labels May 24, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Fixes #31429 (orphaned sessions never committed to OpenViking on CLI startup). Related to #30947 (OpenViking session_id stale after rotation) and #19831 (gateway idle expiry finalization).

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for identifying the startup ordering problem. The specific AttributeError does not exist on current main because cli.py:3975-4030 no longer calls an OpenViking orphan-recovery helper, but the underlying crash-recovery goal remains unsolved on HEAD.

Problems

  • The proposed helper bypasses the provider connection contract: plugins/memory/openviking/__init__.py:878-897 resolves linked ovcli settings, while _VikingClient._headers() at :244-259 includes actor and trusted-mode tenant headers. The CLI helper uses only raw endpoint/API-key environment values and raw requests.
  • Current finalization is provider-owned (plugins/memory/openviking/__init__.py:3147-3235), including writer draining and asynchronous switch finalization. Recovery should use that lifecycle rather than add OpenViking-specific state/HTTP logic to cli.py.

Suggested changes

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform area/sessions Session lifecycle, resume, persistence, history labels Jul 13, 2026
@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Merged via #69191. Your PR's insight — initializing session_id before the orphan commit runs — was addressed by performing recovery inside the provider's initialize() method after self._session_id is set. Thanks for the contribution!

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

Labels

area/sessions Session lifecycle, resume, persistence, history comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants