hermes - 💡(How to fix) Fix Kanban migration crashes on duplicate column: ALTER TABLE ADD COLUMN not idempotent

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

ERROR gateway.run: kanban dispatcher: tick failed on board default Traceback (most recent call last):

Root Cause

Root cause:

Fix Action

Fix / Workaround

The kanban dispatcher fails on every tick with:

ERROR gateway.run: kanban dispatcher: tick failed on board default Traceback (most recent call last): File "/opt/hermes/gateway/run.py", line 3878, in _tick_once_for_board conn = _kb.connect(board=slug) File "/opt/hermes/hermes_cli/kanban_db.py", line 928, in connect _migrate_add_optional_columns(conn) File "/opt/hermes/hermes_cli/kanban_db.py", line 1034, in _migrate_add_optional_columns conn.execute("ALTER TABLE tasks ADD COLUMN max_retries INTEGER") sqlite3.OperationalError: duplicate column name: max_retries

All 14 ALTER TABLE ADD COLUMN statements in _migrate_add_optional_columns() are vulnerable. The first failure crashes the entire migration, preventing the dispatcher from starting.

RAW_BUFFERClick to expand / collapse

The kanban dispatcher fails on every tick with:

ERROR gateway.run: kanban dispatcher: tick failed on board default Traceback (most recent call last): File "/opt/hermes/gateway/run.py", line 3878, in _tick_once_for_board conn = _kb.connect(board=slug) File "/opt/hermes/hermes_cli/kanban_db.py", line 928, in connect _migrate_add_optional_columns(conn) File "/opt/hermes/hermes_cli/kanban_db.py", line 1034, in _migrate_add_optional_columns conn.execute("ALTER TABLE tasks ADD COLUMN max_retries INTEGER") sqlite3.OperationalError: duplicate column name: max_retries

Root cause:

_migrate_add_optional_columns() reads the column list once into a cols set via PRAGMA table_info(tasks), then uses if "col" not in cols guards before each ALTER TABLE ADD COLUMN.

However, this snapshot can be stale when:

  1. Two gateway processes run the migration concurrently (e.g. during a restart)
  2. A previous version's migration partially completed and already added the column

In both cases, the column exists in the actual schema but the cols snapshot doesn't contain it, so the guard passes and the ALTER TABLE fails with duplicate column name.

All 14 ALTER TABLE ADD COLUMN statements in _migrate_add_optional_columns() are vulnerable. The first failure crashes the entire migration, preventing the dispatcher from starting.

Suggested fix:

Wrap each ALTER TABLE ADD COLUMN in a try/except for sqlite3.OperationalError to make the migration idempotent. SQLite lacks IF NOT EXISTS for columns, so this is the standard approach:

python def _safe_add_column(conn, table, column, typedef): try: conn.execute(f"ALTER TABLE {table} ADD COLUMN {column} {typedef}") except sqlite3.OperationalError: pass # column already exists

Environment: latest version, Docker container, WhatsApp gateway.

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

hermes - 💡(How to fix) Fix Kanban migration crashes on duplicate column: ALTER TABLE ADD COLUMN not idempotent