Skip to content

fix(kanban): drop redundant init_db() in gateway watchers (salvage #21874) - #22994

Merged
teknium1 merged 2 commits into
mainfrom
salvage/pr-21874-gateway-double-init
May 10, 2026
Merged

fix(kanban): drop redundant init_db() in gateway watchers (salvage #21874)#22994
teknium1 merged 2 commits into
mainfrom
salvage/pr-21874-gateway-double-init

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Removes the redundant _kb.init_db(board=slug) call from both kanban gateway watchers so the dispatcher and notifier no longer race themselves on every cold start against a legacy DB.

Root cause

Both _kanban_notifier_watcher and _kanban_dispatcher_watcher's _tick_once_for_board opened the kanban DB twice per tick: once via _kb.connect(board=slug) (which auto-runs the migration on first open per process) and again via an explicit _kb.init_db(board=slug) (which deliberately busts the per-process _INITIALIZED_PATHS cache and re-runs the migration on a second connection). The two migrations raced inside the same process, surfacing as either sqlite3.OperationalError: duplicate column name: <col> or intermittent database is locked traces logged at the first tick after every gateway start.

The duplicate-column case was fixed in commit 7869838 (PR #22627 by @wesleysimplicio) which made _add_column_if_missing swallow the duplicate-column error. The wasted second migration plus the database is locked window remain — this PR addresses them by skipping the redundant call entirely.

Changes

  • gateway/run.py: drop _kb.init_db(board=slug) at both sites (notifier watcher loop + dispatcher tick closure). connect() already runs migrations on first open per process.
  • tests/hermes_cli/test_kanban_notify.py: regression tests pinning that neither watcher reintroduces the call (one runtime spy + one source-inspection guard).

Validation

Before After
tests/hermes_cli/test_kanban_notify.py 5/5 7/7
tests/hermes_cli/test_kanban_db.py + test_kanban_core_functionality.py n/a 219/219

Closes #21378 via salvage. Salvage of #21874; original gateway-side fix by @li0near preserved as the committing author. Widened to the second redundant call site (notifier watcher) and added regression tests so the bug can't silently come back. AUTHOR_MAP entry added for li0near's commit email.

li0near and others added 2 commits May 9, 2026 22:36
Both `_kanban_notifier_watcher` and `_kanban_dispatcher_watcher`'s
`_tick_once_for_board` called `_kb.connect(board=slug)` immediately
followed by `_kb.init_db(board=slug)`. Since `connect()` already runs
the schema + idempotent migration on first open per process, the
explicit `init_db()` was redundant — and worse, `init_db()` deliberately
busts the per-process `_INITIALIZED_PATHS` cache and re-runs the migration
on a *second* connection that races the first.

On every cold gateway start against a legacy DB this surfaced as either
`sqlite3.OperationalError: duplicate column name: <col>` or intermittent
`database is locked` errors logged at the first tick. The duplicate-column
case is now tolerated by `_add_column_if_missing` (commit 7869838), but
the wasted second migration plus the database-is-locked race remain
fixable by skipping the redundant call entirely.

Drops `_kb.init_db(board=slug)` at both call sites and adds a regression
test in `tests/hermes_cli/test_kanban_notify.py` that pins the absence
via source inspection plus a runtime spy.

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: salvage/pr-21874-gateway-double-init vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 7970 on HEAD, 7970 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 4210 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

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

Labels

comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sqlite3.OperationalError: database is locked at first kanban dispatcher tick after every gateway startup

3 participants