benbjohnson/litestream · error

created at: %w

Error message

created at: %w

What it means

CalcRestoreTarget computes the time range covered by backups so a restore target time can be validated. This error wraps a failure from r.TimeBounds(ctx), which enumerates LTX files to derive createdAt/updatedAt. If deriving the current (v0.5.x LTX) time bounds fails, restore target calculation aborts with this message.

Source

Thrown at replica.go:566

				createdAt = info.CreatedAt
			}
			if updatedAt.IsZero() || info.CreatedAt.After(updatedAt) {
				updatedAt = info.CreatedAt
			}
		}
		if err := itr.Close(); err != nil {
			return createdAt, updatedAt, err
		}
	}
	return createdAt, updatedAt, nil
}

// CalcRestoreTarget returns a target time restore from.
func (r *Replica) CalcRestoreTarget(ctx context.Context, opt RestoreOptions) (updatedAt time.Time, err error) {
	// Determine the replicated time bounds from LTX files.
	createdAt, updatedAt, err := r.TimeBounds(ctx)
	if err != nil {
		return time.Time{}, fmt.Errorf("created at: %w", err)
	}

	// 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.

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Inspect the wrapped cause from TimeBounds to find whether listing or header parsing failed.
  2. Verify the replica bucket/prefix contains valid LTX files (inspect with `litestream ltx`).
  3. Remove or re-replicate corrupted/truncated LTX objects, or run `litestream reset` locally and let a full sync re-upload.
  4. Check storage credentials and connectivity if listing itself fails.
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure replica has readable LTX objects before computing a restore target
_, err := replica.CalcRestoreTarget(ctx, litestream.RestoreOptions{})
// an empty-timestamp call surfaces time-bound errors early

Try / catch

target, err := replica.CalcRestoreTarget(ctx, opt)
if err != nil && strings.Contains(err.Error(), "created at") {
    // time-bound enumeration failed: inspect wrapped cause, validate LTX objects
}

Prevention

When it happens

Trigger: Calling Replica.CalcRestoreTarget when r.TimeBounds fails — e.g. listing LTX files in storage errors, or a listed LTX file's metadata cannot be read/parsed (corrupt header, truncated object).

Common situations: Corrupted or manually modified LTX objects in storage; partial uploads from a previous crash; storage backend returning errors during listing; wrong bucket/prefix configured so unexpected objects are read.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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