benbjohnson/litestream · error
read ltx page frame: %w
Error message
read ltx page frame: %w
What it means
FetchPage reads the requested page-frame bytes with io.ReadAll and wraps failures as "read ltx page frame". The object was opened but the body read failed, so the page frame is incomplete. The wrapped error carries the actual cause.
Source
Thrown at replica_client.go:164
// Otherwise read the file from the start of the page index.
f, err = client.OpenLTXFile(ctx, info.Level, info.MinTXID, info.MaxTXID, info.Size-ltx.TrailerSize-8-int64(size), 0)
if err != nil {
return nil, fmt.Errorf("open ltx file: %w", err)
}
return f, nil
}
// FetchPage fetches and decodes a single page frame from an LTX file.
func FetchPage(ctx context.Context, client ReplicaClient, level int, minTXID, maxTXID ltx.TXID, offset, size int64) (ltx.PageHeader, []byte, error) {
f, err := client.OpenLTXFile(ctx, level, minTXID, maxTXID, offset, size)
if err != nil {
return ltx.PageHeader{}, nil, fmt.Errorf("open ltx file: %w", err)
}
defer f.Close()
b, err := io.ReadAll(f)
if err != nil {
return ltx.PageHeader{}, nil, fmt.Errorf("read ltx page frame: %w", err)
}
return ltx.DecodePageData(b)
}
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Retry the FetchPage call; per-page reads are cheap and idempotent (inspect the wrapped %w error).
- Add backoff/jitter and limit concurrency when fetching many pages in parallel.
- Increase timeouts on the HTTP/storage client used by the replica backend.
- Check provider status/quota if throttling errors recur.
Example fix
// before: no retry in page loop
hdr, data, err := litestream.FetchPage(ctx, client, level, minTXID, maxTXID, off, sz)
if err != nil { return err }
// after: retry transient read failures per page
hdr, data, err := litestream.FetchPage(ctx, client, level, minTXID, maxTXID, off, sz)
if err != nil && isTransient(err) { hdr, data, err = litestream.FetchPage(ctx, client, level, minTXID, maxTXID, off, sz) } Defensive patterns
Strategy: retry
Validate before calling
if size <= 0 { return fmt.Errorf("invalid page frame size %d", size) } // validate before read Try / catch
hdr, data, err := litestream.FetchPage(ctx, client, level, minTXID, maxTXID, offset, size)
if err != nil && isTransient(err) {
hdr, data, err = litestream.FetchPage(ctx, client, level, minTXID, maxTXID, offset, size)
}
if err != nil { return fmt.Errorf("fetch page @%d: %w", offset, err) } Prevention
- Retry per-page fetches; they are small, idempotent range reads.
- Throttle parallel page fetches to avoid provider throttling.
- Increase client read timeouts for large restores.
- Log wrapped errors with offset to identify repeatedly failing frames.
When it happens
Trigger: Calling FetchPage when the read of the size-bounded page frame from the open LTX file fails — connection reset mid-range-read, storage backend I/O error, or throttling during partial restore.
Common situations: Large restores over unstable networks; S3/GCS throttling (SlowDown) during parallel page fetches; proxies terminating long-lived range reads.
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
- read ltx page index: %w
- close iterator: %w
- fetch ltx files: %w
- copy L0 file: %w
- fetch updated page %d: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/1e80a970b0126e9f.
Report an issue: GitHub.