From 1d4d45bd79d956c49b9e69395dd518117cdda292 Mon Sep 17 00:00:00 2001 From: Brandon Li Date: Tue, 22 Sep 2026 22:07:38 -0500 Subject: [PATCH] Fix build SQLITE_BUSY: busy_timeout before a best-effort WAL switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lib/db.ts switched to WAL at module load before setting busy_timeout. next build imports it from several workers while the live server holds the same file, and a journal-mode change needs the file to itself — so the pragma failed instantly with SQLITE_BUSY and took the whole build down ("Failed to collect page data"), blocking updates on any box whose database was still in rollback mode. The timeout is now set first and the WAL switch is wrapped: a held file keeps its current mode. Co-Authored-By: Claude Opus 5.5 --- lib/db.ts | 13 ++++++++++--- scripts/seed-settings.js | 6 +++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/db.ts b/lib/db.ts index b763018..9a87c73 100644 --- a/lib/db.ts +++ b/lib/db.ts @@ -13,10 +13,17 @@ mkdirSync(path.dirname(DB_PATH), { recursive: true }); const db = new Database(DB_PATH); db.pragma('foreign_keys = ON'); -// If two processes are ever misconfigured onto the same file, WAL + a busy -// timeout turns SQLITE_BUSY crashes into brief contention. -db.pragma('journal_mode = WAL'); +// Timeout first: every later statement, including the journal switch below, +// waits out a concurrent holder instead of failing with SQLITE_BUSY. db.pragma('busy_timeout = 5000'); +// WAL is best-effort. Switching journal mode needs the file to itself, and +// `next build` imports this module from several workers while the live server +// still holds the same file — a hard failure here fails the whole build. +try { + db.pragma('journal_mode = WAL'); +} catch { + // Another connection holds the file; keep its journal mode. +} db.exec(` CREATE TABLE IF NOT EXISTS instruments ( diff --git a/scripts/seed-settings.js b/scripts/seed-settings.js index 46c7af0..abd0662 100644 --- a/scripts/seed-settings.js +++ b/scripts/seed-settings.js @@ -37,8 +37,12 @@ const DB_PATH = process.env.AUTOFIRMER_DB mkdirSync(path.dirname(DB_PATH), { recursive: true }); const db = new Database(DB_PATH); -db.pragma('journal_mode = WAL'); db.pragma('busy_timeout = 5000'); +try { + db.pragma('journal_mode = WAL'); +} catch { + // Another connection holds the file; keep its journal mode. +} // Mirrors the schema in lib/db.ts for every table a restore touches. The app // has usually never run at this point, so the tables may not exist yet; the