benbjohnson/litestream · error
find LTX snapshots: %w
Error message
find LTX snapshots: %w
What it means
Wraps an error from FindLTXFiles when collecting snapshot-level LTX files before a target timestamp. It means the snapshot listing itself failed (as opposed to returning zero matches). The best candidate snapshot could not be determined.
Source
Thrown at replica.go:1503
}
if updatedAt.IsZero() || seg.CreatedAt.After(updatedAt) {
updatedAt = seg.CreatedAt
}
}
}
return createdAt, updatedAt, nil
}
// findBestLTXSnapshotForTimestamp returns the best LTX snapshot for the given timestamp.
// Returns nil if no suitable snapshot exists.
func (r *Replica) findBestLTXSnapshotForTimestamp(ctx context.Context, timestamp time.Time) (*ltx.FileInfo, error) {
// Find snapshots at the snapshot level that are before the timestamp.
snapshots, err := FindLTXFiles(ctx, r.Client, SnapshotLevel, true, func(info *ltx.FileInfo) (bool, error) {
return info.CreatedAt.Before(timestamp), nil
})
if err != nil {
return nil, fmt.Errorf("find LTX snapshots: %w", err)
}
if len(snapshots) == 0 {
return nil, nil
}
// Return the latest snapshot before the timestamp (last in the sorted list).
return snapshots[len(snapshots)-1], nil
}
// CalcRestorePlan returns a list of storage paths to restore a snapshot at the given TXID.
func CalcRestorePlan(ctx context.Context, client ReplicaClient, txID ltx.TXID, timestamp time.Time, logger *slog.Logger) ([]*ltx.FileInfo, error) {
if txID != 0 && !timestamp.IsZero() {
return nil, fmt.Errorf("cannot specify both TXID & timestamp to restore")
}
var infos ltx.FileInfoSlice
logger = logger.With("target", txID)
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Read the wrapped cause and fix the backend listing failure (auth, endpoint, network).
- Retry; use litestream ltx -level all to verify snapshot files are listable.
- Confirm the replica path in config matches the actual bucket layout.
- As a fallback, restore latest without a timestamp.
Example fix
// before
snapshots, err := FindLTXFiles(ctx, r.Client, SnapshotLevel, true, filter)
if err != nil {
return nil, fmt.Errorf("find LTX snapshots: %w", err)
}
// after
// verify listing works:
// $ litestream ltx -level 4 -level 5 <db-path>
// then re-run restore
snapshots, err := FindLTXFiles(ctx, r.Client, SnapshotLevel, true, filter) Defensive patterns
Strategy: try-catch
Try / catch
snapshots, err := findBestLTXSnapshotForTimestamp(ctx, ts)
if err != nil {
// wrapped backend listing error: fix endpoint/auth, then retry with backoff
return fmt.Errorf("snapshot listing failed: %w", err)
}
if snapshots == nil {
// zero matches is NOT an error: fall back to another format
} Prevention
- Validate storage endpoint URLs after provider migrations.
- Refresh session tokens before long DR procedures.
- Distinguish empty-result (nil, nil) from listing errors in custom tooling.
When it happens
Trigger: Restore -> shouldUseV3Restore -> findBestLTXSnapshotForTimestamp: the replica client errors while listing snapshot-level files (network, auth, corrupt listing) rather than simply finding none.
Common situations: Object storage outages during DR drills; expired session tokens; misconfigured endpoint URLs after provider migration.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/133e0067196675c8.
Report an issue: GitHub.