Skip to content

fix: catch IntegrityError on sessions.title UNIQUE index creation - #65628

Closed
AlexFucuson9 wants to merge 1 commit into
NousResearch:mainfrom
AlexFucuson9:fix/integrity-error-sessions-title-unique-v2
Closed

fix: catch IntegrityError on sessions.title UNIQUE index creation#65628
AlexFucuson9 wants to merge 1 commit into
NousResearch:mainfrom
AlexFucuson9:fix/integrity-error-sessions-title-unique-v2

Conversation

@AlexFucuson9

Copy link
Copy Markdown
Contributor

Summary

hermes_state.py line 1783 creates a UNIQUE index on sessions.title but only catches sqlite3.OperationalError. When duplicate titles exist in the database, SQLite throws sqlite3.IntegrityError instead — which is uncaught, crashing Dashboard API calls to /api/sessions/{id}/messages.

Root Cause

Commit 60b6abefd (feat: session naming with unique titles) added the UNIQUE INDEX but only catches OperationalError ("index already exists"). It doesn't handle the case where the index doesn't exist yet but the table already has duplicate titles — which throws IntegrityError.

This can happen through:

  • Session imports with non-unique titles
  • Context compression creating duplicate continuation titles
  • Race conditions in concurrent session creation

Fix

Catch sqlite3.IntegrityError before OperationalError. When caught:

  1. Deduplicate sessions by keeping the newest row per title
  2. Retry the index creation

Changes

  • hermes_state.py: Add IntegrityError handler with deduplication logic

Test Plan

  • Unit tests pass
  • Verified with duplicate titles in test database
  • Dashboard API no longer crashes on duplicate session titles

Fixes #65602

When duplicate titles exist in the sessions table, CREATE UNIQUE INDEX
throws sqlite3.IntegrityError instead of OperationalError. The previous
code only caught OperationalError, causing Dashboard API crashes.

Fix: catch IntegrityError, deduplicate by keeping newest row, then
retry index creation. This handles:
- Session imports with non-unique titles
- Context compression creating duplicate continuation titles
- Race conditions in concurrent session creation

Fixes NousResearch#65602
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard comp/dashboard Web dashboard / control panel UI (dashboard/, landing) needs-decision Awaiting maintainer decision before any implementation sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Jul 16, 2026

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Comment

Scope

  • 1 file (hermes_state.py), +12 lines
  • Handles IntegrityError when creating a UNIQUE index on sessions.title if duplicate titles already exist — deduplicates by keeping newest row before retrying the index creation.

Observations

  • Correct error handling: Catches the specific IntegrityError, deduplicates with a clear strategy (keep newest), then retries the index creation.
  • GROUP BY + MAX(rowid) is a standard SQLite deduplication pattern — appropriate here.
  • Minor: the WHERE clause in the DELETE subquery is redundant since the index is already filtered on , but harmless.

Looks Good

  • Focused, well-scoped fix for a real DB migration edge case
  • No impact on other code paths

Reviewed by Hermes Agent

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Comment

Scope

  • 1 file (hermes_state.py), +12 lines
  • Handles IntegrityError when creating a UNIQUE index on sessions.title if duplicate titles exist — deduplicates by keeping newest row before retrying the index creation.

Quality

  • GROUP BY + MAX(rowid) is a standard SQLite deduplication pattern.
  • Clear, focused fix for a real DB migration edge case.
  • No impact on other code paths.

Looks Good

  • Well-scoped error handling in schema init.

Reviewed by Hermes Agent

@teknium1

Copy link
Copy Markdown
Contributor

Closing in favor of PR #65689 (salvaged from #65636). You were first on this bug and the IntegrityError diagnosis was spot-on — thank you for the report-quality root cause. The reason we went with the other implementation: the dedup DELETE here keeps only MAX(rowid) per non-null-title group, which means every untitled session (the majority of normal sessions) falls outside the subquery and gets deleted, along with their transcripts. #65689 repairs by NULLing the older duplicate aliases instead, preserving every row. Credited you in the merged PR discussion — thanks again for surfacing this.

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

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/dashboard Web dashboard / control panel UI (dashboard/, landing) needs-decision Awaiting maintainer decision before any implementation P2 Medium — degraded but workaround exists 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.

fix: catch IntegrityError on sessions.title UNIQUE index creation

4 participants