benbjohnson/litestream · error

read page size: %w

Error message

read page size: %w

What it means

Litestream failed to read the database page size via `PRAGMA page_size` during init. Page size is required to interpret WAL frames and build LTX files. The error wraps the driver-level Scan error — typically a locked/closed connection, context cancellation, or an unreadable database header.

Source

Thrown at db.go:1103

	if _, err := db.db.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS _litestream_seq (id INTEGER PRIMARY KEY, seq INTEGER);`); err != nil {
		return fmt.Errorf("create _litestream_seq table: %w", err)
	}

	// Create a lock table to force write locks during sync.
	// The sync write transaction always rolls back so no data should be in this table.
	if _, err := db.db.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS _litestream_lock (id INTEGER);`); err != nil {
		return fmt.Errorf("create _litestream_lock table: %w", err)
	}

	// Start a long-running read transaction to prevent other transactions
	// from checkpointing.
	if err := db.acquireReadLock(ctx); err != nil {
		return fmt.Errorf("acquire read lock: %w", err)
	}

	// Read page size.
	if err := db.db.QueryRowContext(ctx, `PRAGMA page_size;`).Scan(&db.pageSize); err != nil {
		return fmt.Errorf("read page size: %w", err)
	} else if db.pageSize <= 0 {
		return fmt.Errorf("invalid db page size: %d", db.pageSize)
	}

	// Ensure meta directory structure exists.
	if err := internal.MkdirAll(db.metaPath, db.dirInfo); err != nil {
		return err
	}

	// Ensure WAL has at least one frame in it.
	if err := db.ensureWALExists(ctx); err != nil {
		return fmt.Errorf("ensure wal exists: %w", err)
	}

	// Check if database is behind replica (issue #781).
	// This must happen before replica.Start() to detect restore scenarios.
	if db.Replica != nil {
		if err := db.checkDatabaseBehindReplica(ctx); err != nil {

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Confirm the database file still exists and is a valid SQLite file (`sqlite3 file 'PRAGMA page_size;'` directly).
  2. Restore the database from backup if the header is corrupted.
  3. Increase/fix the context passed to Open so slow starts aren't cancelled.
  4. Re-run Litestream; if transient (network FS), move the DB to local storage.

Example fix

// before
# file copied with `cp` mid-write -> 'file is not a database'
// after
sqlite3 app.db '.backup app.db.bak' && mv app.db.bak app.db   # consistent copy, then restart litestream
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: readable file with valid sqlite header
const hdr = fs.readFileSync(dbPath).subarray(0, 16).toString('latin1');
if (!hdr.startsWith('SQLite format 3')) throw new Error('invalid sqlite header');

Type guard

function hasSqliteHeader(p) {
  try { const fd = fs.openSync(p, 'r'); const b = Buffer.alloc(16); fs.readSync(fd, b, 0, 16, 0); fs.closeSync(fd); return b.toString('latin1').startsWith('SQLite format 3'); } catch { return false; }
}

Try / catch

try {
  await db.Open(ctx);
} catch (err) {
  if (String(err.message).includes('read page size')) {
    logger.error('cannot read page size; check file integrity', { cause: err.cause });
    // fall back to `litestream restore` into a fresh file
  }
}

Prevention

When it happens

Trigger: The `QueryRowContext(ctx, "PRAGMA page_size;").Scan(&db.pageSize)` call fails during db.init: connection lost, context cancelled, file unreadable/corrupt header so SQLite cannot respond, or database file replaced/deleted between open and this query.

Common situations: Database file deleted or truncated while Litestream is initializing; corrupted header from a partial file copy; context deadline exceeded during a slow start; running against an unsupported/foreign file format.

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/897676eb2a11ffe9. Report an issue: GitHub.