benbjohnson/litestream · error
encode ltx snapshot header: %w
Error message
encode ltx snapshot header: %w
What it means
Wraps a failure to encode the LTX snapshot header (version, page size, commit, WAL offset/size, salts, timestamp) into the snapshot stream. Encoding writes bytes through the pipe, so failures mean the pipe consumer has closed/cancelled or the header fields were rejected as invalid by the encoder. It aborts the entire snapshot stream via pw.CloseWithError.
Source
Thrown at db.go:2880
enc, err := ltx.NewEncoder(pw)
if err != nil {
pw.CloseWithError(fmt.Errorf("new ltx encoder: %w", err))
return
}
if err := enc.EncodeHeader(ltx.Header{
Version: ltx.Version,
Flags: ltx.HeaderFlagNoChecksum,
PageSize: uint32(pos.pageSize),
Commit: commit,
MinTXID: 1,
MaxTXID: pos.pos.TXID,
Timestamp: time.Now().UnixMilli(),
WALOffset: walOffset,
WALSize: walSize,
WALSalt1: rd.salt1,
WALSalt2: rd.salt2,
}); err != nil {
pw.CloseWithError(fmt.Errorf("encode ltx snapshot header: %w", err))
return
}
if err := db.writeLTXFromDB(ctx, enc, walFile, commit, pageMap); err != nil {
pw.CloseWithError(fmt.Errorf("write snapshot ltx: %w", err))
return
}
if err := enc.Close(); err != nil {
pw.CloseWithError(fmt.Errorf("close ltx snapshot encoder: %w", err))
return
}
_ = pw.Close()
}()
return &snapshotReadCloser{PipeReader: pr, pos: pos}, nil
}
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Check the consumer for an earlier error or premature close; the root cause is usually on the reading side
- Ensure pageSize/commit values are initialized before starting a snapshot (the caller already guards pageSize==0)
- Retry the snapshot with a stable, unclosed reader and sufficient timeout
- If header values look invalid, verify the database was opened and initialized before replication
Defensive patterns
Strategy: try-catch
Validate before calling
// verify db initialized (page size set) before snapshot
if st := db.SyncStatus(); st == dbStatusOffline { return errors.New("db not initialized") } Try / catch
err := streamSnapshot(ctx, db)
if err != nil && strings.Contains(err.Error(), "encode ltx snapshot header") {
// almost always a consumer-side early close/cancel; inspect consumer first
return fmt.Errorf("snapshot consumer aborted: %w", err)
} Prevention
- Keep the pipe consumer reading until EOF
- Open and initialize the database before starting replication
- Avoid mid-stream cancellation; cancel only with intent to abort
- Check the first error on the pipe — later header/write errors are secondary
When it happens
Trigger: enc.EncodeHeader(ltx.Header{...}) fails during snapshot generation: pipe reader closed early, context-cancelled consumer, or an invalid header field (e.g. zero/invalid PageSize because pageSize was not initialized).
Common situations: Consumer stops reading on an earlier error leaving the producer to fail on the next write; restore timeout elapsing mid-header; a pageSize of 0 slipping through due to a racing database initialization.
Related errors
- close ltx snapshot encoder: %w
- encode ltx frame (pgno=%d): %w
- write snapshot ltx: %w
- snapshot interval must be greater than 0
- new ltx encoder: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/0bec3f1822bc83bc.
Report an issue: GitHub.