benbjohnson/litestream · error
write ltx from db: %w
Error message
write ltx from db: %w
What it means
db.writeLTXFromDB failed with a non-disk-full error while copying pages from the database file and WAL into the snapshot LTX. This is the page-copy phase of snapshot replication; failures here abort the snapshot and the staged temp file is removed by the deferred os.Remove.
Source
Thrown at db.go:2179
}
return result, fmt.Errorf("encode ltx header: %w", err)
}
// If we need a full snapshot, then copy from the database & WAL.
// Otherwise, just copy incrementally from the WAL.
if info.snapshotting {
db.setSyncDiagPhase(diagPhaseWriteLTXFromDB,
func(s *diagState) {
s.txID = txID
s.walSize = sz
s.snapshotting = true
s.reason = info.reason
})
if err := db.writeLTXFromDB(ctx, enc, walFile, commit, pageMap); err != nil {
if isDiskFullError(err) {
return result, NewLTXError("stage-write", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf("%w: %w", ErrDiskFull, err))
}
return result, fmt.Errorf("write ltx from db: %w", err)
}
} else {
db.setSyncDiagPhase(diagPhaseWriteLTXFromWAL,
func(s *diagState) {
s.txID = txID
s.walSize = sz
s.snapshotting = false
s.reason = info.reason
})
if err := db.writeLTXFromWAL(ctx, enc, walFile, info.prevCommit, commit, pageMap); err != nil {
if isDiskFullError(err) {
return result, NewLTXError("stage-write", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf("%w: %w", ErrDiskFull, err))
}
return result, fmt.Errorf("write ltx from wal: %w", err)
}
}
// Encode final trailer to the end of the LTX file.View on GitHub (pinned to 4ed7a308f6)
Solutions
- Verify DB integrity: run `sqlite3 <db> 'PRAGMA integrity_check;'` and check the WAL file is intact.
- Ensure only litestream manages the database files — stop tools that copy/rotate the db or WAL.
- Check dmesg for read I/O errors on the database volume.
- Re-run replication; if local LTX state is broken, `litestream reset` for the database.
- Ensure litestream is not being stopped/restarted mid-snapshot (init system restart loops).
Example fix
// before: nightly rsync job copies db + wal while litestream runs 0 * * * * rsync -a /data/app.db /backup/ // after: use sqlite backup or litestream restore instead 0 * * * * litestream restore -o /backup/app.db /data/app.db
Defensive patterns
Strategy: try-catch
Validate before calling
if err := sqliteIntegrityCheck(dbPath); err != nil {
return fmt.Errorf("db corrupt, fix before replication: %w", err)
}
// integrity_check via sqlite3 CLI: sqlite3 db 'PRAGMA integrity_check;' Try / catch
var le *os.PathError
if errors.As(err, &le) && errors.Is(le.Err, syscall.EIO) {
log.Printf("read I/O error on %s during snapshot: %v", le.Path, le.Err)
// check hardware, restore from backup, then reset
} Prevention
- Never let other tools read-modify or copy live db/WAL files; use litestream restore for copies
- Run periodic PRAGMA integrity_check
- Avoid restarting litestream mid-snapshot; use graceful shutdown
- Monitor storage health on the DB volume
When it happens
Trigger: Read errors on the database file or WAL file during page iteration (I/O error, file truncated/corrupted mid-copy), context cancellation from the caller, or an ltx encoder error propagating from page writes.
Common situations: Corrupt or externally modified DB/WAL files (another tool touching the SQLite files); storage failures on the DB volume; litestream shutdown mid-snapshot causing context cancellation.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- encode ltx header: %w
- write ltx from wal: %w
- close ltx encoder: %w
- open temp ltx file: %w
- new ltx encoder: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/5af5cc1af70db024.
Report an issue: GitHub.