benbjohnson/litestream · error

fetch ltx files: %w

Error message

fetch ltx files: %w

What it means

Replica.ValidateLevel lists LTX files at a compaction level by calling r.Client.LTXFiles(ctx, level, 0, false) to obtain a file iterator. This error wraps a failure to open/enumerate the remote (or local) LTX file listing from the replica client, so validation cannot proceed and no ValidationError list is produced.

Source

Thrown at replica.go:1787

	return txid, nil
}

// ValidationError represents a single validation issue.
type ValidationError struct {
	Level    int           // compaction level
	Type     string        // "gap", "overlap", or "unsorted"
	Message  string        // human-readable description
	PrevFile *ltx.FileInfo // previous file
	CurrFile *ltx.FileInfo // current file that caused error
}

// ValidateLevel checks LTX files at the given level are sorted and contiguous.
// Returns a slice of validation errors (empty if valid).
func (r *Replica) ValidateLevel(ctx context.Context, level int) ([]ValidationError, error) {
	itr, err := r.Client.LTXFiles(ctx, level, 0, false)
	if err != nil {
		return nil, fmt.Errorf("fetch ltx files: %w", err)
	}
	defer itr.Close()

	var errors []ValidationError
	var prevInfo *ltx.FileInfo

	for itr.Next() {
		info := itr.Item()

		// Skip first file - nothing to compare against
		if prevInfo == nil {
			prevInfo = info
			continue
		}

		// Check for sort order: curr.MinTXID should be >= prev.MinTXID
		if info.MinTXID < prevInfo.MinTXID {
			errors = append(errors, ValidationError{

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Run 'litestream replicas' or check the replica URL to confirm storage configuration (bucket, prefix, region, endpoint)
  2. Verify cloud credentials/permissions (s3:Get/List on the bucket prefix) and that they are not expired
  3. Test network connectivity to the storage endpoint from the host running validation
  4. Check that the compaction level passed to ValidateLevel is valid (0–9) and that files exist at that level

Example fix

// before
itr, err := client.LTXFiles(ctx, level, 0, false)
// after: verify connectivity and creds before validating
if err := clientHelmetCheck(ctx, r.Client); err != nil { return err }
itr, err := r.Client.LTXFiles(ctx, level, 0, false)
if err != nil { return fmt.Errorf("fetch ltx files at level %d: %w", level, err) }
Defensive patterns

Strategy: retry

Validate before calling

// Validate replica config before calling ValidateLevel
if r.Client == nil { return fmt.Errorf("replica client not initialized") }
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()

Type guard

func clientReady(r *Replica) bool { return r != nil && r.Client != nil }

Try / catch

errs, err := r.ValidateLevel(ctx, level)
if err != nil {
    // transient storage/network failures: retry with backoff
    errs, err = retryWithBackoff(3, func() ([]ValidationError, error) {
        return r.ValidateLevel(ctx, level)
    })
}

Prevention

When it happens

Trigger: Calling ValidateLevel (or validation commands that use it) when the storage backend's LTXFiles listing fails: S3/GS/Azure credentials invalid or expired, bucket/container missing, network unreachable, or the storage client was not initialized for that level.

Common situations: Wrong bucket name or region in litestream.yml; expired cloud credentials (IAM role rotated, token expired); firewall/egress blocking the storage endpoint; s3 replica with a path that no longer exists after a 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/38cfcfc14998145f. Report an issue: GitHub.