benbjohnson/litestream · error

no backups found

Error message

no backups found

What it means

When RestoreOptions.Timestamp is set, CalcRestoreTarget requires known time bounds (createdAt/updatedAt) to validate the requested timestamp. If both bounds are zero — meaning no backups of any format were found in the replica — restore target computation fails with 'no backups found'. It indicates the replica has nothing restorable, not that the timestamp is out of range.

Source

Thrown at replica.go:587

	// Also check v0.3.x time bounds if client supports it.
	if client, ok := r.Client.(ReplicaClientV3); ok {
		v3CreatedAt, v3UpdatedAt, err := r.TimeBoundsV3(ctx, client)
		if err != nil {
			return time.Time{}, fmt.Errorf("v0.3.x time bounds: %w", err)
		}
		// Extend time bounds to include v0.3.x backups.
		if !v3CreatedAt.IsZero() && (createdAt.IsZero() || v3CreatedAt.Before(createdAt)) {
			createdAt = v3CreatedAt
		}
		if !v3UpdatedAt.IsZero() && (updatedAt.IsZero() || v3UpdatedAt.After(updatedAt)) {
			updatedAt = v3UpdatedAt
		}
	}

	// Skip if it does not contain timestamp.
	if !opt.Timestamp.IsZero() {
		if createdAt.IsZero() && updatedAt.IsZero() {
			return time.Time{}, fmt.Errorf("no backups found")
		}
		if opt.Timestamp.Before(createdAt) || opt.Timestamp.After(updatedAt) {
			return time.Time{}, fmt.Errorf("timestamp does not exist")
		}
	}

	return updatedAt, nil
}

// Replica restores the database from a replica based on the options given.
// This method will restore into opt.OutputPath, if specified, or into the
// DB's original database path. It can optionally restore from a specific
// replica or it will automatically choose the best one. Finally,
// a timestamp can be specified to restore the database to a specific
// point-in-time.
//
// When the replica contains both v0.3.x and LTX format backups, this method
// compares snapshots from both formats and uses whichever has the better backup:

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Verify the replica actually has backups: run `litestream ltx` / list the storage location.
  2. Check the config's bucket/prefix/replica path points to the location containing backups.
  3. Run a sync (`litestream replicate`) to create an initial backup before restoring.
  4. If backups were deleted by retention/lifecycle policies, restore from a different replica or snapshot.
Defensive patterns

Strategy: validation

Validate before calling

// check the replica has backups before a timestamped restore
infos, err := client.ListLTXFiles(ctx, 0)
if err != nil || len(infos) == 0 {
    return fmt.Errorf("replica %s has no backups", replicaName)
}

Try / catch

err := replica.Restore(ctx, opt)
if err != nil && errors.Is(err, errors.New("no backups found")) || strings.Contains(err.Error(), "no backups found") {
    // fall back to another replica or create a fresh backup first
}

Prevention

When it happens

Trigger: CalcRestoreTarget (and thus restore with -timestamp) is called on a replica whose storage contains no LTX files and no legacy backups, so TimeBounds/TimeBoundsV3 returned zero timestamps.

Common situations: Typo in config bucket/prefix pointing at an empty location; a replica that never completed its first sync; storage cleaned by lifecycle policies; using the wrong replica name in restore command.

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/2d9ad2dac1a20b16. Report an issue: GitHub.