benbjohnson/litestream · error
decode page: %w
Error message
decode page: %w
What it means
This error is returned by Replica.applyLTXFile while streaming pages out of an LTX transaction file during replication/restore. The underlying ltx.Decoder.DecodePage failed, meaning the page stream is corrupt, truncated, or the header/pageSize does not match what was encoded. Litestream treats it as a fatal LTX integrity failure because a partial page application would corrupt the database.
Source
Thrown at replica.go:971
dec := ltx.NewDecoder(rc)
if err := dec.DecodeHeader(); err != nil {
return fmt.Errorf("decode header: %w", err)
}
hdr := dec.Header()
if err := internal.LockFileExclusive(f); err != nil {
return fmt.Errorf("acquire exclusive lock: %w", err)
}
defer internal.UnlockFile(f)
for {
var phdr ltx.PageHeader
data := make([]byte, pageSize)
if err := dec.DecodePage(&phdr, data); err == io.EOF {
break
} else if err != nil {
return fmt.Errorf("decode page: %w", err)
}
if phdr.Pgno == 1 && len(data) >= 28 {
data[18], data[19] = 0x01, 0x01
_, _ = rand.Read(data[24:28])
}
off := int64(phdr.Pgno-1) * int64(pageSize)
if _, err := f.WriteAt(data, off); err != nil {
return fmt.Errorf("write page %d: %w", phdr.Pgno, err)
}
}
if hdr.Commit > 0 {
if err := f.Sync(); err != nil {
return fmt.Errorf("sync before truncate: %w", err)
}
newSize := int64(hdr.Commit) * int64(pageSize)View on GitHub (pinned to 4ed7a308f6)
Solutions
- Run `litestream reset <db>` to discard corrupted local LTX state and re-sync from the replica
- Delete or quarantine the corrupted LTX object in remote storage so the replica re-uploads a valid one
- Verify network stability between the host and the storage backend (retries/proxy timeouts)
- Confirm the LTX file was produced by a compatible Litestream/LTX version; re-create the replica with a matching version
Example fix
// before: silently skipping or retrying a corrupt file
currentTXID = info.MaxTXID
// after: surface the error and reset state
if err := r.applyLTXFile(ctx, f, info, pageSize); err != nil {
return fmt.Errorf("decode page: %w", err) // then run: litestream reset <db>
} Defensive patterns
Strategy: try-catch
Validate before calling
func ltxLooksIntact(info *ltx.FileInfo, rc io.Reader) error {
dec := ltx.NewDecoder(rc)
if err := dec.DecodeHeader(); err != nil { return err }
buf := make([]byte, dec.Header().PageSize)
for {
var ph ltx.PageHeader
if err := dec.DecodePage(&ph, buf); err == io.EOF { break } else if err != nil { return err }
}
return dec.Close()
} Try / catch
err := r.applyLTXFile(ctx, f, info, pageSize)
var ltxErr *ltx.Error
if errors.As(err, <xErr) || strings.Contains(err.Error(), "decode page") {
// corrupted stream: reset local state and re-sync
exec.Command("litestream", "reset", dbPath).Run()
return fmt.Errorf("ltx stream corrupt, state reset: %w", err)
}
return err Prevention
- Monitor storage object sizes/etags to catch partial uploads
- Never modify LTX files after creation; they are immutable
- Keep litestream and LTX format versions consistent across replicas
- Alert on replication errors immediately — fail silently and corruption compounds
When it happens
Trigger: dec.DecodePage returns a non-EOF error inside the page loop: corrupted/truncated LTX file in storage, a remote replica stream interrupted mid-read, an LTX file written by an incompatible LTX format version, or a pageSize mismatch between the DB and the LTX header.
Common situations: Interrupted uploads leaving partial LTX objects in S3/GCS, manual edits or re-compression of LTX files, restoring across Litestream versions with differing LTX formats, network disconnects during replica sync/follow mode, storage lifecycle policies truncating objects.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- verify
- extract timestamp from LTX header: %w
- apply gap-fill ltx file (level=%d, min=%s, max=%s): %w
- peek header: %w
- invalid replica, checksum mismatch
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/34fd883c81b0a6e7.
Report an issue: GitHub.