benbjohnson/litestream · error
extract timestamp from LTX header: %w
Error message
extract timestamp from LTX header: %w
What it means
uploadSizedLTX extracts the timestamp by calling ltx.PeekHeader on the reader; if the LTX header cannot be parsed, this error wraps the parse failure. It means the bytes at the start of the file are not a valid LTX header — the file is corrupt, truncated, or not an LTX file at all. The upload is aborted to avoid replicating garbage.
Source
Thrown at s3/replica_client.go:790
return c.uploadStreamedLTX(ctx, key, r, partSize)
}
// uploadSizedLTX uploads from a seekable reader whose size is known.
func (c *ReplicaClient) uploadSizedLTX(ctx context.Context, key string, rs io.ReadSeeker, start, partSize int64) (int64, time.Time, *string, error) {
end, err := rs.Seek(0, io.SeekEnd)
if err != nil {
return 0, time.Time{}, nil, fmt.Errorf("s3: size ltx file %s: %w", key, err)
}
size := end - start
if _, err := rs.Seek(start, io.SeekStart); err != nil {
return 0, time.Time{}, nil, fmt.Errorf("s3: rewind ltx file %s: %w", key, err)
}
// Extract timestamp from LTX header, then rewind so the upload sees the
// full file.
hdr, _, err := ltx.PeekHeader(rs)
if err != nil {
return 0, time.Time{}, nil, fmt.Errorf("extract timestamp from LTX header: %w", err)
}
timestamp := time.UnixMilli(hdr.Timestamp).UTC()
if _, err := rs.Seek(start, io.SeekStart); err != nil {
return 0, time.Time{}, nil, fmt.Errorf("s3: rewind ltx file %s: %w", key, err)
}
input := c.putObjectInput(key, timestamp)
input.Body = rs
if size < partSize {
input.ContentLength = aws.Int64(size)
out, err := c.s3.PutObject(ctx, input)
if err != nil {
return 0, time.Time{}, nil, fmt.Errorf("s3: put object %s: %w", key, err)
}
return size, timestamp, out.ETag, nil
}
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Inspect the wrapped error to see the specific header parse failure
- Delete the corrupt LTX file and let litestream recreate it from the live database (or run 'litestream reset' for the database to clear corrupted local LTX state)
- Verify disk health (fsck / SMART) if corruption is recurring
- Ensure nothing else writes into the replica's LTX directory
Example fix
// recover from a corrupt local LTX file $ litestream reset /path/to/db $ systemctl restart litestream
Defensive patterns
Strategy: validation
Validate before calling
if _, _, err := ltx.PeekHeader(f); err != nil {
return fmt.Errorf("LTX file %s corrupt: %w", path, err)
} Try / catch
if err != nil && strings.Contains(err.Error(), "extract timestamp from LTX header") {
// corrupt/truncated LTX file: remove it or run 'litestream reset' for the DB
} Prevention
- Verify disk health if header corruption recurs
- Never let external tools write into the litestream replica directory
- Use 'litestream reset' to clear corrupted local LTX state
When it happens
Trigger: PeekHeader fails on a truncated LTX file (crash mid-write), a zero-length or partially initialized temp file, bit-rot on disk, or a file that was accidentally overwritten by non-LTX data.
Common situations: Host crash or power loss leaving a partial LTX file; disk corruption; buggy external tooling writing into the replica directory; restoring/moving litestream data directories incorrectly.
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
- extract timestamp from LTX header: %w
- extract timestamp from LTX header: %w
- extract timestamp from LTX header: %w
- peek header: %w
- decode ltx header: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/4ab5a642c1a0991c.
Report an issue: GitHub.