benbjohnson/litestream · error

target time required

Error message

target time required

What it means

Returned by VFSFile.SetTargetTime (time-travel read view) when the caller passes a zero time.Time. The method rebuilds the page index at a specific point in time; a zero timestamp is meaningless for CalcRestorePlan, so it is rejected up front with this sentinel error.

Source

Thrown at vfs.go:1253

		f.syncStop = make(chan struct{})
		stopCh := f.syncStop
		tickerCh := f.syncTicker.C
		f.wg.Add(1)
		go func() { defer f.wg.Done(); f.syncLoop(stopCh, tickerCh) }()
	}

	// 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)
}

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Check timestamp.IsZero() before calling SetTargetTime and skip/branch to ResetTime when unset
  2. Parse the user-supplied time with error handling so a parse failure doesn't silently yield a zero time
  3. Use ResetTime(ctx) when you actually want the latest state instead of a target time

Example fix

// before
var target time.Time
file.SetTargetTime(ctx, target) // panics-free but errors
// after
if target.IsZero() {
    err = file.ResetTime(ctx)
} else {
    err = file.SetTargetTime(ctx, target)
}
Defensive patterns

Strategy: validation

Validate before calling

if targetTime.IsZero() { return errors.New("target time required before SetTargetTime") }

Type guard

func hasTarget(t time.Time) bool { return !t.IsZero() }

Try / catch

if err := file.SetTargetTime(ctx, t); err != nil {
    if err.Error() == "target time required" {
        return file.ResetTime(ctx) // fall back to latest
    }
    return err
}

Prevention

When it happens

Trigger: Calling SetTargetTime(ctx, time.Time{}) — e.g. an unset struct field, a failed JSON/DB decode of the target time, or a var declared without initialization — instead of a real restore timestamp.

Common situations: App config where the restore-time option is optional and left empty; deserialization of a missing timestamp field defaulting to the zero value; passing time.Now() result stored in a zero-valued variable due to an earlier error.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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