hermes - 💡(How to fix) Fix Kanban archive race: remove_board() doesn't clear _INITIALIZED_PATHS, causing empty DB + no such table: task_events [1 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

Archiving a kanban board via the dashboard UI causes a no such table: task_events error in the event stream WebSocket. The board's data is moved to _archived/ but an empty DB is immediately recreated without schema initialization, breaking any active SSE/WebSocket consumers. 4. Observe the dashboard log: WARNING hermes_dashboard_plugin_kanban: Kanban event stream error: no such table: task_events The except Exception catch-all should distinguish between a missing-table error (board was archived/removed) and other failures. On OperationalError with "no such table", the handler should close the WebSocket cleanly rather than logging a generic warning.

Root Cause

kanban_db.remove_board() (hermes_cli/kanban_db.py ~line 511) moves the board directory to _archived/ but does not call _INITIALIZED_PATHS.discard() for the old DB path.

The event stream WebSocket handler (plugins/kanban/dashboard/plugin_api.py ~line 1565) runs a poll loop calling kanban_db.connect(board=slug) every few seconds. After the archive:

  1. connect() resolves the (now-deleted) board path
  2. path.parent.mkdir(parents=True, exist_ok=True) recreates the empty board directory
  3. sqlite3.connect() creates a new empty .db file
  4. Since the path is still cached in _INITIALIZED_PATHS, the CREATE TABLE IF NOT EXISTS schema init is skipped
  5. The query SELECT ... FROM task_events WHERE id > ? fails → OperationalError: no such table: task_events

Fix Action

Fixed

Code Example

def remove_board(slug: str, *, archive: bool = True) -> dict:
    normed = _normalize_board_slug(slug)
    # ... existing validation ...
    d = board_dir(normed)
    if not d.exists():
        raise ValueError(f"board {normed!r} does not exist")

    # --- ADD THIS: clear the init cache so connect() doesn't skip schema ---
    db_file = d / "kanban.db"
    _INITIALIZED_PATHS.discard(str(db_file.resolve()))
    # ---

    if get_current_board() == normed:
        clear_current_board()
    # ... rest of function ...
RAW_BUFFERClick to expand / collapse

Bug Summary

Archiving a kanban board via the dashboard UI causes a no such table: task_events error in the event stream WebSocket. The board's data is moved to _archived/ but an empty DB is immediately recreated without schema initialization, breaking any active SSE/WebSocket consumers.

Steps to Reproduce

  1. Open the Hermes Dashboard → Kanban plugin
  2. Select a board (e.g. test-board)
  3. Click "Archive"
  4. Observe the dashboard log: WARNING hermes_dashboard_plugin_kanban: Kanban event stream error: no such table: task_events

Root Cause

kanban_db.remove_board() (hermes_cli/kanban_db.py ~line 511) moves the board directory to _archived/ but does not call _INITIALIZED_PATHS.discard() for the old DB path.

The event stream WebSocket handler (plugins/kanban/dashboard/plugin_api.py ~line 1565) runs a poll loop calling kanban_db.connect(board=slug) every few seconds. After the archive:

  1. connect() resolves the (now-deleted) board path
  2. path.parent.mkdir(parents=True, exist_ok=True) recreates the empty board directory
  3. sqlite3.connect() creates a new empty .db file
  4. Since the path is still cached in _INITIALIZED_PATHS, the CREATE TABLE IF NOT EXISTS schema init is skipped
  5. The query SELECT ... FROM task_events WHERE id > ? fails → OperationalError: no such table: task_events

Suggested Fix

1. Clear the path cache in remove_board() (kanban_db.py):

def remove_board(slug: str, *, archive: bool = True) -> dict:
    normed = _normalize_board_slug(slug)
    # ... existing validation ...
    d = board_dir(normed)
    if not d.exists():
        raise ValueError(f"board {normed!r} does not exist")

    # --- ADD THIS: clear the init cache so connect() doesn't skip schema ---
    db_file = d / "kanban.db"
    _INITIALIZED_PATHS.discard(str(db_file.resolve()))
    # ---

    if get_current_board() == normed:
        clear_current_board()
    # ... rest of function ...

2. Guard the event stream handler (plugin_api.py ~line 1608):

The except Exception catch-all should distinguish between a missing-table error (board was archived/removed) and other failures. On OperationalError with "no such table", the handler should close the WebSocket cleanly rather than logging a generic warning.

Environment

  • Hermes Agent: installed from source (latest as of 2026-05-11)
  • OS: Debian 12 (VPS)
  • Python: 3.12
  • Dashboard served via systemd + Caddy reverse proxy

Additional Context

  • The board also remains listed in the UI after archiving (shows 0 tasks, archive button still visible) because the DELETE endpoint returns success but the board metadata isn't fully marked as archived in the active board listing.
  • The rogue empty kanban.db that gets recreated can also confuse the telemetry importer and other board consumers.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING