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
- 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).
- 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).
- Pass an absolute path for the database file to avoid cwd-resolution surprises.
- 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
- Pin Node 22.5+ and document the --experimental-sqlite flag where applicable.
- Always pass an absolute path located in a known-writable app data directory.
- Create and write-check the data directory at app startup, before opening the DB.
- Surface process.version and the resolved path in the error context for fast triage.
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
- Migration "${migration.name}" (sequence ${migration.sequence
- Unknown statement: "${name}"
- Failed to export ${environmentType} environments.
- Failed to process ${parsedFile.fileName}: ${err.message}
- Failed to parse the file – ensure it is valid JSON or YAML
AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13).
Data as JSON: /api/errors/7aa25915774bfcee.
Report an issue: GitHub.