benbjohnson/litestream · error

open database: %w

Error message

open database: %w

What it means

EnableDB calls db.Open() to start replication; this error wraps any failure Open returns (SQLite open failure, replica client init, config problems). Note db.Open() does not support context cancellation, so once reached, the open runs to completion and its error is surfaced here.

Source

Thrown at store.go:397

// The context is checked for cancellation before opening.
// Note: db.Open() itself does not support cancellation.
func (s *Store) EnableDB(ctx context.Context, path string) error {
	db := s.FindDB(path)
	if db == nil {
		return fmt.Errorf("database not found: %s", path)
	}

	if db.IsOpen() {
		return fmt.Errorf("database already enabled: %s", path)
	}

	// Check for cancellation before starting open
	if err := ctx.Err(); err != nil {
		return fmt.Errorf("enable database: %w", err)
	}

	if err := db.Open(); err != nil {
		return fmt.Errorf("open database: %w", err)
	}

	return nil
}

// DisableDB stops replication for a database.
func (s *Store) DisableDB(ctx context.Context, path string) error {
	db := s.FindDB(path)
	if db == nil {
		return fmt.Errorf("database not found: %s", path)
	}

	if !db.IsOpen() {
		return fmt.Errorf("database already disabled: %s", path)
	}

	if err := db.Close(ctx); err != nil {
		return fmt.Errorf("close database: %w", err)

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Read the wrapped cause from the error chain and fix the underlying open failure
  2. Verify the SQLite file exists and the process has read/write access to it and its directory
  3. Validate replica client config (bucket, credentials, endpoint) before enabling
  4. Retry with backoff if the failure was transient (e.g. storage briefly unavailable)

Example fix

// before
err := store.EnableDB(ctx, path) // opaque open failure
// after
if err := store.EnableDB(ctx, path); err != nil {
    log.Printf("enable %s failed: %v", path, err) // prints wrapped cause
}
// ensure perms: chmod u+rw /path/to/app.db
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.Stat(dbPath); err != nil {
    return fmt.Errorf("sqlite file inaccessible: %w", err)
}
if f, err := os.OpenFile(dbPath, os.O_RDWR, 0); err != nil {
    return fmt.Errorf("sqlite file not writable: %w", err)
} else { f.Close() }

Try / catch

if err := store.EnableDB(ctx, path); err != nil {
    if strings.Contains(err.Error(), "open database:") {
        log.Printf("open failed: %v", err) // wrapped root cause
        // validate file, perms, replica config, then retry with backoff
    }
    return err
}

Prevention

When it happens

Trigger: Store.EnableDB(ctx, path) where db.Open() fails: SQLite file missing/unreadable, directory not writable for WAL/SHM, bad replica configuration, or the DB was concurrently opened/closed.

Common situations: Wrong db path in the enable request; permissions changed after registration; replica storage credentials invalid; disk full or read-only filesystem preventing WAL creation.

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


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/aa3f984f5bc0804c. Report an issue: GitHub.