{"record":{"id":"897676eb2a11ffe9","repo":"benbjohnson/litestream","slug":"read-page-size-w","errorCode":null,"errorMessage":"read page size: %w","messagePattern":"read page size: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":1103,"sourceCode":"\tif _, err := db.db.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS _litestream_seq (id INTEGER PRIMARY KEY, seq INTEGER);`); err != nil {\n\t\treturn fmt.Errorf(\"create _litestream_seq table: %w\", err)\n\t}\n\n\t// Create a lock table to force write locks during sync.\n\t// The sync write transaction always rolls back so no data should be in this table.\n\tif _, err := db.db.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS _litestream_lock (id INTEGER);`); err != nil {\n\t\treturn fmt.Errorf(\"create _litestream_lock table: %w\", err)\n\t}\n\n\t// Start a long-running read transaction to prevent other transactions\n\t// from checkpointing.\n\tif err := db.acquireReadLock(ctx); err != nil {\n\t\treturn fmt.Errorf(\"acquire read lock: %w\", err)\n\t}\n\n\t// Read page size.\n\tif err := db.db.QueryRowContext(ctx, `PRAGMA page_size;`).Scan(&db.pageSize); err != nil {\n\t\treturn fmt.Errorf(\"read page size: %w\", err)\n\t} else if db.pageSize <= 0 {\n\t\treturn fmt.Errorf(\"invalid db page size: %d\", db.pageSize)\n\t}\n\n\t// Ensure meta directory structure exists.\n\tif err := internal.MkdirAll(db.metaPath, db.dirInfo); err != nil {\n\t\treturn err\n\t}\n\n\t// Ensure WAL has at least one frame in it.\n\tif err := db.ensureWALExists(ctx); err != nil {\n\t\treturn fmt.Errorf(\"ensure wal exists: %w\", err)\n\t}\n\n\t// Check if database is behind replica (issue #781).\n\t// This must happen before replica.Start() to detect restore scenarios.\n\tif db.Replica != nil {\n\t\tif err := db.checkDatabaseBehindReplica(ctx); err != nil {","sourceCodeStart":1085,"sourceCodeEnd":1121,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L1085-L1121","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Confirm the database file still exists and is a valid SQLite file (`sqlite3 file 'PRAGMA page_size;'` directly).","Restore the database from backup if the header is corrupted.","Increase/fix the context passed to Open so slow starts aren't cancelled.","Re-run Litestream; if transient (network FS), move the DB to local storage."],"exampleFix":"// before\n# file copied with `cp` mid-write -> 'file is not a database'\n// after\nsqlite3 app.db '.backup app.db.bak' && mv app.db.bak app.db   # consistent copy, then restart litestream","handlingStrategy":"try-catch","validationCode":"// preflight: readable file with valid sqlite header\nconst hdr = fs.readFileSync(dbPath).subarray(0, 16).toString('latin1');\nif (!hdr.startsWith('SQLite format 3')) throw new Error('invalid sqlite header');","typeGuard":"function hasSqliteHeader(p) {\n  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; }\n}","tryCatchPattern":"try {\n  await db.Open(ctx);\n} catch (err) {\n  if (String(err.message).includes('read page size')) {\n    logger.error('cannot read page size; check file integrity', { cause: err.cause });\n    // fall back to `litestream restore` into a fresh file\n  }\n}","preventionTips":["Never copy/replace the live DB file with a partial write; use sqlite3 .backup or VACUUM INTO.","Restore from replica if integrity_check fails.","Avoid storage that truncates files on crash.","Don't cancel the Open context mid-init."],"tags":["sqlite","pragma","init","corruption"],"backgroundTag":"database-query-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}