{"record":{"id":"9c05b222b56e726c","repo":"decolua/9router","slug":"db-no-sqlite-driver-available-bun-better-node-s","errorCode":null,"errorMessage":"[DB] No SQLite driver available (bun/better/node/sql.js all failed)","messagePattern":"\\[DB\\] No SQLite driver available \\(bun/better/node/sql\\.js all failed\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/lib/db/driver.js","lineNumber":64,"sourceCode":"  try {\n    const { createSqlJsAdapter } = await import(\"./adapters/sqljsAdapter.js\");\n    return await createSqlJsAdapter(DATA_FILE);\n  } catch (e) {\n    console.warn(`[DB] sql.js unavailable: ${e.message}`);\n    return null;\n  }\n}\n\nasync function initAdapter() {\n  ensureDirs();\n  // Order per runtime:\n  //   Bun:  bun:sqlite → sql.js\n  //   Node: better-sqlite3 → node:sqlite (≥22.5) → sql.js\n  let adapter = await tryBunSqlite();\n  if (!adapter) adapter = await tryBetterSqlite();\n  if (!adapter) adapter = await tryNodeSqlite();\n  if (!adapter) adapter = await trySqlJs();\n  if (!adapter) throw new Error(\"[DB] No SQLite driver available (bun/better/node/sql.js all failed)\");\n\n  if (!state.logged) {\n    console.log(`[DB] Driver: ${adapter.driver} | file: ${DATA_FILE}`);\n    state.logged = true;\n  }\n\n  const { runMigrationOnce } = await import(\"./migrate.js\");\n  await runMigrationOnce(adapter);\n  return adapter;\n}\n\nexport async function getAdapter() {\n  if (state.instance) return state.instance;\n  if (!state.initPromise) state.initPromise = initAdapter().then((a) => { state.instance = a; return a; });\n  return state.initPromise;\n}\n\nexport function getAdapterSync() {","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/db/driver.js#L46-L82","documentation":"initAdapter walks a fallback chain of SQLite backends — bun:sqlite, better-sqlite3, node:sqlite, and the pure-JS sql.js — and throws this error only when every one fails to initialize. It means the process has no usable way to open DATA_FILE, so all DB-backed features are down. Each attempt is logged upstream; the throw happens after the last (sql.js) attempt also returns null.","triggerScenarios":"Running on Node without better-sqlite3 installed/buildable, Node <22.5 (no node:sqlite), not on Bun, and sql.js unavailable (missing dependency or WASM load failure).","commonSituations":"npm install skipped optionalDependencies (--omit=optional) so better-sqlite3 native build never ran; native module ABI mismatch after a Node major upgrade; constrained/alpine containers lacking build tools for node-gyp; a corrupted or unwritable DATA_DIR/`~/.9router` making every driver fail to open the file; exotic runtimes (Edge, Electron renderer) where none of the drivers load.","solutions":["Reinstall with optionals enabled: `npm install` (not --omit=optional) so better-sqlite3 is built, and check its install/build logs.","On Node >= 22.5 prefer node:sqlite; upgrade Node or set DATA_DIR to a writable path if the file open was the failure point.","Check earlier log lines from tryBunSqlite/tryBetterSqlite/tryNodeSqlite/trySqlJs to see each driver's specific failure (module not found vs. SQLITE_CANTOPEN vs. WASM load).","Ensure DATA_DIR (default ~/.9router) exists and is writable by the process user; fix permissions or point DATA_DIR elsewhere and restart.","As a last resort verify sql.js is resolvable (it is the always-works fallback) — if even it fails, the dependency tree or WASM assets are broken and a clean reinstall is needed."],"exampleFix":"// before\nnpm ci --omit=optional   # better-sqlite3 never installed; no driver loads\n// after\nnpm install              # optional deps built; [DB] Driver: better-sqlite3 | file: ~/.9router/db.sqlite","handlingStrategy":"fallback","validationCode":"async function assertSqliteAvailable() {\n  try { const a = await getAdapter(); return !!a; }\n  catch (err) {\n    if (String(err.message).includes('No SQLite driver available')) return false;\n    throw err;\n  }\n}\n// call at startup: if (!(await assertSqliteAvailable())) show fatal setup error","typeGuard":null,"tryCatchPattern":"try {\n  const db = await getAdapter();\n} catch (err) {\n  if (String(err.message).includes('[DB] No SQLite driver available')) {\n    console.error('Fatal: no SQLite backend. Reinstall with `npm install` so better-sqlite3 builds, or run on Node >=22.5 / Bun.');\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Install with optional dependencies enabled so better-sqlite3 (the preferred native driver) is built on Node.","Pin/upgrade to Node >= 22.5 (built-in node:sqlite) or run under Bun (bun:sqlite) to remove the native-build dependency.","Ensure DATA_DIR (default ~/.9router) exists and is writable before startup; a bad file path makes every driver fail.","After Node major upgrades, rebuild native modules (npm rebuild better-sqlite3) to avoid ABI mismatches.","Check the per-driver failure logs printed before the throw — they distinguish 'module missing' from 'cannot open database file'."],"tags":["sqlite","database","driver","native-dependency","startup"],"backgroundTag":"no-sqlite-driver-available","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}