benbjohnson/litestream · error

no backup files available

Error message

no backup files available

What it means

Returned by VFSFile.SetTargetTime when the computed restore plan contains zero LTX files, meaning the replica has no backup files that can represent the database at the requested timestamp. The library throws this because building a page index from an empty plan is impossible.

Source

Thrown at vfs.go:1260

	// Start compaction monitors if enabled
	if f.compactor != nil && f.vfs != nil {
		f.startCompactionMonitors()
	}

	return nil
}

// SetTargetTime rebuilds the page index to view the database at a specific time.
func (f *VFSFile) SetTargetTime(ctx context.Context, timestamp time.Time) error {
	if timestamp.IsZero() {
		return fmt.Errorf("target time required")
	}

	infos, err := CalcRestorePlan(ctx, f.client, 0, timestamp, f.logger)
	if err != nil {
		return fmt.Errorf("cannot calc restore plan: %w", err)
	} else if len(infos) == 0 {
		return fmt.Errorf("no backup files available")
	}

	// Disable hydrated reads during time travel - hydrated file is at latest state
	if f.hydrator != nil && f.hydrator.Complete() {
		f.hydrator.Disable()
		f.logger.Debug("hydration disabled for time travel", "target", timestamp)
	}

	return f.rebuildIndex(ctx, infos, &timestamp)
}

// ResetTime rebuilds the page index to the latest available state.
func (f *VFSFile) ResetTime(ctx context.Context) error {
	infos, err := CalcRestorePlan(ctx, f.client, 0, time.Time{}, f.logger)
	if err != nil {
		return fmt.Errorf("cannot calc restore plan: %w", err)
	} else if len(infos) == 0 {
		return fmt.Errorf("no backup files available")

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Pick a target timestamp within the replica's retention window (after the earliest snapshot)
  2. Confirm the replica has any LTX files at all (litestream ltx listing) and that the client points at the right bucket/path
  3. Re-replicate from the primary if the replica was wiped or retention deleted needed files

Example fix

// before
file.SetTargetTime(ctx, oldTime) // before earliest snapshot
// after
if earliest := replicas.EarliestTimestamp(); oldTime.Before(earliest) {
    oldTime = earliest
}
file.SetTargetTime(ctx, oldTime)
Defensive patterns

Strategy: validation

Validate before calling

infos, err := client.LTXInfos(ctx)
if err != nil || len(infos) == 0 { return errors.New("replica has no LTX files") }

Type guard

func replicaHasBackups(infos []*ltx.FileInfo) bool { return len(infos) > 0 }

Try / catch

if err := file.SetTargetTime(ctx, t); err != nil {
    if err.Error() == "no backup files available" {
        return file.ResetTime(ctx) // or surface a clear user message
    }
    return err
}

Prevention

When it happens

Trigger: CalcRestorePlan succeeds but returns no infos: the replica is empty, the target timestamp is before any existing snapshot, or all applicable LTX files were removed by retention/compaction.

Common situations: New replica not yet having completed its first snapshot; requesting time travel to a point older than the retention window; wrong bucket/path configured so no LTX files are visible.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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