benbjohnson/litestream · error

set journal mode: %w

Error message

set journal mode: %w

What it means

populateDatabase in the litestream-test helper wraps the failure to execute PRAGMA page_size in this error. The PRAGMA runs immediately after opening the test database to set the page size before WAL mode is enabled; SQLite only honors page_size before any table is created. If the PRAGMA fails, the test database cannot be sized as requested and population aborts.

Source

Thrown at cmd/litestream-test/populate.go:85

}

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)

		createSQL := fmt.Sprintf(`
			CREATE TABLE %s (
				id INTEGER PRIMARY KEY AUTOINCREMENT,
				data BLOB,
				text_field TEXT,
				int_field INTEGER,
				float_field REAL,
				timestamp INTEGER
			)

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Use a valid SQLite page size: a power of two between 512 and 65536 (default 4096).
  2. Verify the parent directory of the database file exists and is writable.
  3. Ensure no other process holds a lock on the database file when populating.
  4. Enable PRAGMA journal_mode = WAL before setting page_size if the database already exists with data.

Example fix

// before
cfg.PageSize = 3000 // invalid
// after
cfg.PageSize = 4096 // power of two, 512..65536
Defensive patterns

Strategy: validation

Validate before calling

if cfg.PageSize != 0 && (cfg.PageSize < 512 || cfg.PageSize > 65536 || cfg.PageSize&(cfg.PageSize-1) != 0) {
    return fmt.Errorf("invalid page size %d: must be power of two between 512 and 65536", cfg.PageSize)
}

Try / catch

if _, err := db.Exec(fmt.Sprintf("PRAGMA page_size = %d", cfg.PageSize)); err != nil {
    var sqliteErr sqlite.Error
    if errors.As(err, &sqliteErr) {
        log.Printf("page_size pragma failed with code %d", sqliteErr.Code)
    }
    return fmt.Errorf("set page size: %w", err)
}

Prevention

When it happens

Trigger: The db.Exec("PRAGMA page_size = N") call fails: invalid page size value, a locked or corrupted database file, an unwritable database path, or the connection has already been used so page_size is read-only.

Common situations: Configuring PageSize to a value not a power of two between 512 and 65536; pointing DB at a file in a non-existent directory; another process (or a stale litestream instance) holds a lock on the database file.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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