benbjohnson/litestream · error

fetch ltx files: %w

Error message

fetch ltx files: %w

What it means

EnforceSnapshotRetention could not open the LTX file iterator for the snapshot level (SnapshotLevel) because c.client.LTXFiles returned an error; the retention sweep aborts with 'fetch ltx files: <err>'. No snapshot files are evaluated or deleted when this fires — it's a listing failure at the storage layer, before any cleanup happens.

Source

Thrown at compactor.go:244

	}

	if err := itr.Close(); err != nil {
		return fmt.Errorf("close iterator: %w", err)
	}

	return nil
}

// EnforceSnapshotRetention enforces retention of snapshot level files by timestamp.
// Files older than the retention duration are deleted (except the newest is always kept).
// Returns the minimum snapshot TXID still retained (useful for cascading retention to lower levels).
func (c *Compactor) EnforceSnapshotRetention(ctx context.Context, retention time.Duration) (ltx.TXID, error) {
	timestamp := time.Now().Add(-retention)
	c.logger.Debug("enforcing snapshot retention", "timestamp", timestamp)

	itr, err := c.client.LTXFiles(ctx, SnapshotLevel, 0, false)
	if err != nil {
		return 0, fmt.Errorf("fetch ltx files: %w", err)
	}
	defer itr.Close()

	var deleted []*ltx.FileInfo
	var lastInfo *ltx.FileInfo
	var minSnapshotTXID ltx.TXID

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

		if info.CreatedAt.Before(timestamp) {
			deleted = append(deleted, info)
			continue
		}

		if minSnapshotTXID == 0 || info.MaxTXID < minSnapshotTXID {
			minSnapshotTXID = info.MaxTXID

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Inspect the wrapped error — auth vs network vs missing bucket/prefix
  2. Verify replica storage config (endpoint, bucket, prefix, credentials) with `litestream ltx -level <n>` or a direct storage listing
  3. Re-authenticate / fix IAM permissions so listing snapshot-level files is allowed
  4. Check network/VPN to the storage endpoint; retry after outage
  5. Ensure the local replica directory wasn't deleted; run `litestream reset <db>` if local LTX state is corrupt
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight listing before relying on retention:
itr, err := client.LTXFiles(ctx, litestream.SnapshotLevel, 0, false)
if err != nil { log.Fatalf("storage listing unavailable: %v", err) }
itr.Close()

Try / catch

if err := compactor.EnforceSnapshotRetention(ctx, retention); err != nil {
    if strings.Contains(err.Error(), "fetch ltx files") {
        // check credentials/bucket, then retry with backoff
    }
}

Prevention

When it happens

Trigger: Called by monitorSnapshots when enforcing snapshot retention; the storage client fails to list snapshot-level files — missing bucket/prefix, revoked credentials, network failure, context canceled, or the ReplicaClient not supporting listing for that level.

Common situations: S3 credentials expired or IAM policy lacking ListObjectsV2; bucket/prefix misconfigured in the replica config; storage outage; local file replica directory removed out-of-band; retention monitor running against a replica client that can't reach the remote.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/15aac93623140581. Report an issue: GitHub.