{"record":{"id":"2f1497c30b8f278b","repo":"benbjohnson/litestream","slug":"created-at-w","errorCode":null,"errorMessage":"created at: %w","messagePattern":"created at: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"replica.go","lineNumber":566,"sourceCode":"\t\t\t\tcreatedAt = info.CreatedAt\n\t\t\t}\n\t\t\tif updatedAt.IsZero() || info.CreatedAt.After(updatedAt) {\n\t\t\t\tupdatedAt = info.CreatedAt\n\t\t\t}\n\t\t}\n\t\tif err := itr.Close(); err != nil {\n\t\t\treturn createdAt, updatedAt, err\n\t\t}\n\t}\n\treturn createdAt, updatedAt, nil\n}\n\n// CalcRestoreTarget returns a target time restore from.\nfunc (r *Replica) CalcRestoreTarget(ctx context.Context, opt RestoreOptions) (updatedAt time.Time, err error) {\n\t// Determine the replicated time bounds from LTX files.\n\tcreatedAt, updatedAt, err := r.TimeBounds(ctx)\n\tif err != nil {\n\t\treturn time.Time{}, fmt.Errorf(\"created at: %w\", err)\n\t}\n\n\t// Also check v0.3.x time bounds if client supports it.\n\tif client, ok := r.Client.(ReplicaClientV3); ok {\n\t\tv3CreatedAt, v3UpdatedAt, err := r.TimeBoundsV3(ctx, client)\n\t\tif err != nil {\n\t\t\treturn time.Time{}, fmt.Errorf(\"v0.3.x time bounds: %w\", err)\n\t\t}\n\t\t// Extend time bounds to include v0.3.x backups.\n\t\tif !v3CreatedAt.IsZero() && (createdAt.IsZero() || v3CreatedAt.Before(createdAt)) {\n\t\t\tcreatedAt = v3CreatedAt\n\t\t}\n\t\tif !v3UpdatedAt.IsZero() && (updatedAt.IsZero() || v3UpdatedAt.After(updatedAt)) {\n\t\t\tupdatedAt = v3UpdatedAt\n\t\t}\n\t}\n\n\t// Skip if it does not contain timestamp.","sourceCodeStart":548,"sourceCodeEnd":584,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/replica.go#L548-L584","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Inspect the wrapped cause from TimeBounds to find whether listing or header parsing failed.","Verify the replica bucket/prefix contains valid LTX files (inspect with `litestream ltx`).","Remove or re-replicate corrupted/truncated LTX objects, or run `litestream reset` locally and let a full sync re-upload.","Check storage credentials and connectivity if listing itself fails."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// ensure replica has readable LTX objects before computing a restore target\n_, err := replica.CalcRestoreTarget(ctx, litestream.RestoreOptions{})\n// an empty-timestamp call surfaces time-bound errors early","typeGuard":null,"tryCatchPattern":"target, err := replica.CalcRestoreTarget(ctx, opt)\nif err != nil && strings.Contains(err.Error(), \"created at\") {\n    // time-bound enumeration failed: inspect wrapped cause, validate LTX objects\n}","preventionTips":["Inspect replicas with `litestream ltx` to catch corrupt objects early","Avoid manual edits/deletions inside the replica storage prefix","Ensure uploads complete atomically so no truncated LTX files persist"],"tags":["restore","time-bounds","ltx"],"backgroundTag":"database-query-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}