benbjohnson/litestream · error
open database: %w
Error message
open database: %w
What it means
populateDatabase calls os.Remove on any existing database, then opens the (new) file with `sql.Open("sqlite3", c.DB)` and wraps failures as "open database". Since database/sql's Open is lazy, this error generally means a bad DSN/path or an unavailable driver rather than a runtime connection problem; actual file-level failures typically appear at the first Exec (see "set page size").
Source
Thrown at cmd/litestream-test/populate.go:76
"page_size", c.PageSize,
)
if err := c.populateDatabase(ctx, targetBytes); err != nil {
return fmt.Errorf("populate database: %w", err)
}
slog.Info("Database population complete", "db", c.DB)
return nil
}
func (c *PopulateCommand) populateDatabase(ctx context.Context, targetBytes int64) error {
if err := os.Remove(c.DB); err != nil && !os.IsNotExist(err) {
slog.Warn("Could not remove existing database", "error", err)
}
db, err := sql.Open("sqlite3", c.DB)
if err != nil {
return fmt.Errorf("open database: %w", err)
}
defer db.Close()
if _, err := db.Exec(fmt.Sprintf("PRAGMA page_size = %d", c.PageSize)); err != nil {
return fmt.Errorf("set page size: %w", err)
}
if _, err := db.Exec("PRAGMA journal_mode = WAL"); err != nil {
return fmt.Errorf("set journal mode: %w", err)
}
if _, err := db.Exec("PRAGMA synchronous = NORMAL"); err != nil {
return fmt.Errorf("set synchronous: %w", err)
}
for i := 0; i < c.TableCount; i++ {
tableName := fmt.Sprintf("test_table_%d", i)
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Ensure the -db value is a file path in a writable directory (not a directory itself) and check parent-directory write permissions.
- Verify the sqlite3 driver is registered in the build (correct import/CGO setup) and rebuild if needed.
- If the real failure appears only on the first Exec, look at the subsequent wrapped errors ("set page size", "set journal mode") for the file-level root cause.
Example fix
// before
db, err := sql.Open("sqlite3", c.DB)
if err != nil {
return fmt.Errorf("open database: %w", err)
}
// after — detect file-level open failures eagerly
db, err := sql.Open("sqlite3", c.DB)
if err != nil {
return fmt.Errorf("open database: %w", err)
}
if err := db.Ping(); err != nil {
return fmt.Errorf("open database: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
import { statSync } from "fs";
if (existsSync(dbPath) && statSync(dbPath).isDirectory()) {
throw new Error(`-db must be a file path, not a directory: ${dbPath}`);
}
if (!statSync(path.dirname(dbPath)).isDirectory()) throw new Error("parent directory missing: " + path.dirname(dbPath)); Type guard
function isWritableFilePath(p) {
try { return !existsSync(p) || statSync(p).isFile(); } catch { return false; }
} Try / catch
try {
await run("litestream-test", ["populate", "-db", dbPath]);
} catch (e) {
if (String(e).includes("open database")) {
console.error(`Could not open ${dbPath}; check it is a file path in a writable directory and the sqlite3 driver is built in.`);
}
throw e;
} Prevention
- Pass a file path (not a directory) to -db and ensure the parent directory is writable.
- Ensure the binary is built with the sqlite3 driver registered.
- Avoid odd characters in paths that could corrupt the DSN.
When it happens
Trigger: `litestream-test populate -db <path>` where the DSN is rejected by the driver, the sqlite3 driver is not registered in the build, or the driver fails immediately opening the path (unwritable directory, path is a directory, invalid characters in path).
Common situations: -db pointing at an existing directory instead of a file path; unwritable parent directory; building without the sqlite3 driver import; path characters that break the DSN.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- open database: %w
- database does not exist: %w
- ensure test table: %w
- populate database: %w
- set page size: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/fc07f7d68f57ad2b.
Report an issue: GitHub.