usebruno/bruno · critical · Error

Failed to open the database.

Error message

Failed to open the database.

What it means

Thrown by createDatabase as a defensive guard after constructing DB(path, migrations, dbOptions): if db._db is undefined, the underlying node:sqlite DatabaseSync handle is unusable. The DB constructor sets _db = new DatabaseSync(path, options) and, on migration failure, closes it and sets _db = undefined before re-throwing the migration error; the only way to reach this guard with _db undefined (and no prior throw) is when DatabaseSync itself fails to yield a usable handle — most often because node:sqlite is unavailable in the running Node build or the file path is inaccessible.

Source

Thrown at packages/bruno-sqlite/src/node/index.ts:25

export { DB } from './db';
export type { DatabaseOptions } from './db';
export { Statements } from './statements';
export type { OnMutation } from './statements';
export { registerSQLiteIpc } from './ipc';
export type { IpcMainLike } from './ipc';
export * from '../shared';

export const version = '0.1.0';

export type CreateDatabaseOptions = DatabaseOptions & {
  onMutation?: OnMutation;
};

export const createDatabase = (path: string, options: CreateDatabaseOptions = {}) => {
  const { onMutation, ...dbOptions } = options;
  const db = new DB(path, migrations, dbOptions);
  if (db._db === undefined) {
    throw new Error('Failed to open the database.');
  }
  const statements = new Statements(db._db, onMutation);
  return { db, statements };
};

View on GitHub (pinned to 9bdd81c7bd)

Solutions

  1. Run on Node 22.5+ and, where node:sqlite is still experimental, launch with --experimental-sqlite (or set the equivalent flag in your process launcher).
  2. Verify the data directory exists and is writable by the process before calling createDatabase (fs.mkdirSync(dir, { recursive: true }) and an fs.accessSync write check).
  3. Pass an absolute path for the database file to avoid cwd-resolution surprises.
  4. Check available disk space and filesystem quotas if the handle fails to initialize.

Example fix

// before
const { db, statements } = createDatabase('./data.db');

// after
const path = require('path');
const fs = require('fs');
const dir = path.resolve(process.env.BRUNO_DATA_DIR || './data');
fs.mkdirSync(dir, { recursive: true });
fs.accessSync(dir, fs.constants.W_OK);
const { db, statements } = createDatabase(path.join(dir, 'app.db'));
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
const path = require('path');
function preflightDbPath(p) {
  const dir = path.dirname(path.resolve(p));
  fs.mkdirSync(dir, { recursive: true });
  fs.accessSync(dir, fs.constants.W_OK | fs.constants.R_OK);
  // node:sqlite availability
  try { require('node:sqlite'); } catch { throw new Error('node:sqlite unavailable — use Node 22.5+ with --experimental-sqlite if required'); }
}
preflightDbPath(dbPath);
const { db, statements } = createDatabase(dbPath, options);

Try / catch

try {
  return createDatabase(dbPath, options);
} catch (e) {
  if (/Failed to open the database\./.test(e?.message)) {
    throw new Error(`Could not open SQLite at '${dbPath}'. Check Node ${process.version} supports node:sqlite, the directory is writable, and disk has space.`);
  }
  throw e;
}

Prevention

When it happens

Trigger: createDatabase is invoked with a path on a read-only or non-existent directory, a path the process lacks permission to create/write, or under a Node.js build/version where node:sqlite is not compiled in or is disabled. It can also surface if DatabaseSync throws in a way that the constructor swallows, leaving _db unset without re-throwing.

Common situations: Running on Node < 22.5 (or a distro build without experimental sqlite compiled in) where node:sqlite is absent; forgot --experimental-sqlite on a Node version where it is still flagged; data directory does not exist or is read-only (snap/appimage/sandbox); file path is a relative path resolved against an unexpected cwd; disk full or quota exceeded at open time.

Related errors


AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13). Data as JSON: /api/errors/7aa25915774bfcee. Report an issue: GitHub.