benbjohnson/litestream · error
extract timestamp from LTX header: %w
Error message
extract timestamp from LTX header: %w
What it means
Wraps a failure from ltx.PeekHeader when the file replica client reads an incoming LTX stream to extract its timestamp during WriteLTXFile. The header could not be parsed, meaning the payload is not a valid LTX file (empty, truncated, corrupted, or wrong format), so the write is aborted rather than persisting a file with an unknown timestamp.
Source
Thrown at file/replica_client.go:171
return f, nil
}
// WriteLTXFile writes an LTX file to the replica.
// Extracts timestamp from LTX header and sets it as the file's ModTime to preserve original creation time.
func (c *ReplicaClient) WriteLTXFile(ctx context.Context, level int, minTXID, maxTXID ltx.TXID, rd io.Reader) (info *ltx.FileInfo, err error) {
var fileInfo, dirInfo os.FileInfo
if db := c.db(); db != nil {
fileInfo, dirInfo = db.FileInfo(), db.DirInfo()
}
// Use TeeReader to peek at LTX header while preserving data for upload
var buf bytes.Buffer
teeReader := io.TeeReader(rd, &buf)
// Extract timestamp from LTX header
hdr, _, err := ltx.PeekHeader(teeReader)
if err != nil {
return nil, fmt.Errorf("extract timestamp from LTX header: %w", err)
}
timestamp := time.UnixMilli(hdr.Timestamp).UTC()
// Combine buffered data with rest of reader
fullReader := io.MultiReader(&buf, rd)
// Ensure parent directory exists.
filename := c.LTXFilePath(level, minTXID, maxTXID)
if err := internal.MkdirAll(filepath.Dir(filename), dirInfo); err != nil {
return nil, err
}
// Write LTX file to temporary file next to destination path.
tmpFilename := filename + ".tmp"
f, err := internal.CreateFile(tmpFilename, fileInfo)
if err != nil {
return nil, err
}View on GitHub (pinned to 4ed7a308f6)
Solutions
- Verify the producer emits complete, valid LTX data (check the DB's local LTX files).
- Check litestream/ltx library version compatibility between writer and replica.
- Re-run replication from the source; if local LTX state is corrupted, use `litestream reset`.
- Ensure nothing truncates the stream between producer and replica (disk space, fd limits).
Example fix
// before
rd := getReader() // may be empty
_, err := client.WriteLTXFile(ctx, level, minTXID, maxTXID, rd)
// after
data, err := io.ReadAll(getReader())
if len(data) == 0 { return fmt.Errorf("empty ltx payload, refusing write") }
_, err = client.WriteLTXFile(ctx, level, minTXID, maxTXID, bytes.NewReader(data)) Defensive patterns
Strategy: validation
Validate before calling
hdr, _, err := ltx.PeekHeader(bytes.NewReader(buf.Bytes()))
if err != nil { return fmt.Errorf("payload is not valid LTX: %w", err) } Try / catch
if _, err := client.WriteLTXFile(ctx, level, minTXID, maxTXID, rd); err != nil {
if strings.Contains(err.Error(), "extract timestamp from LTX header") { return fmt.Errorf("corrupt ltx stream: %w", err) }
return err
} Prevention
- Ensure producers write complete LTX files (check disk space, fd limits).
- Keep litestream and ltx library versions in sync.
- Never feed an already-consumed or empty reader to WriteLTXFile.
When it happens
Trigger: WriteLTXFile receiving a reader whose first bytes are not a valid LTX header: zero-byte upload, partially flushed writer, corrupted transfer, or a non-LTX payload written to a file replica.
Common situations: Disk-full or interrupted transfer producing truncated LTX data; version mismatch between the writer and the ltx package; caller passing an empty or already-consumed reader.
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
- decode page: %w
- apply gap-fill ltx file (level=%d, min=%s, max=%s): %w
- peek header: %w
- extract timestamp from LTX header: %w
- decode ltx header: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/1da2f544cb551a6c.
Report an issue: GitHub.