From 8ac3cf29120fe6c5bbf32b075e46c01e99a5f75e Mon Sep 17 00:00:00 2001 From: gavrielc Date: Sun, 10 May 2026 22:28:55 +0300 Subject: [PATCH] fix(container): gracefully handle missing on_wake column in pre-migration session DBs The container opens inbound.db read-only, so it can't ALTER TABLE. If the host hasn't run migrateMessagesInTable yet (e.g., container rebuilt before host restart), the on_wake column won't exist and the query crashes, causing a restart loop. Detect the column via PRAGMA table_info and conditionally include the filter clause. Co-Authored-By: Claude Opus 4.6 (1M context) --- container/agent-runner/src/db/messages-in.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/container/agent-runner/src/db/messages-in.ts b/container/agent-runner/src/db/messages-in.ts index d3a1a33..dc6eeac 100644 --- a/container/agent-runner/src/db/messages-in.ts +++ b/container/agent-runner/src/db/messages-in.ts @@ -10,6 +10,19 @@ import { getConfig } from '../config.js'; import { openInboundDb, getOutboundDb } from './connection.js'; +// Cache whether inbound.db has the on_wake column (added in v2.0.48). +// The container opens inbound.db read-only, so it can't ALTER — +// gracefully degrade when running against an older session DB. +let _hasOnWake: boolean | null = null; +function hasOnWakeColumn(db: ReturnType): boolean { + if (_hasOnWake !== null) return _hasOnWake; + const cols = new Set( + (db.prepare("PRAGMA table_info('messages_in')").all() as Array<{ name: string }>).map((c) => c.name), + ); + _hasOnWake = cols.has('on_wake'); + return _hasOnWake; +} + export interface MessageInRow { id: string; seq: number | null; @@ -54,12 +67,13 @@ export function getPendingMessages(isFirstPoll = false): MessageInRow[] { const outbound = getOutboundDb(); try { + const onWakeFilter = hasOnWakeColumn(inbound) ? 'AND (on_wake = 0 OR ?1 = 1)' : ''; const pending = inbound .prepare( `SELECT * FROM messages_in WHERE status = 'pending' AND (process_after IS NULL OR datetime(process_after) <= datetime('now')) - AND (on_wake = 0 OR ?1 = 1) + ${onWakeFilter} ORDER BY seq DESC LIMIT ?2`, )