{"record":{"id":"32bcf066e2a19ba6","repo":"benbjohnson/litestream","slug":"get-ltx-time-bounds-w","errorCode":null,"errorMessage":"get LTX time bounds: %w","messagePattern":"get LTX time bounds: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"replica.go","lineNumber":1410,"sourceCode":"\t// Sort by CreatedAt for timestamp-based selection.\n\tsortSnapshotsV3ByCreatedAt(allSnapshots)\n\n\treturn findBestSnapshotV3(allSnapshots, timestamp), nil\n}\n\n// shouldUseV3Restore determines whether to use v0.3.x restore instead of LTX.\n// Returns true if v0.3.x has a better backup for the given options.\nfunc (r *Replica) shouldUseV3Restore(ctx context.Context, client ReplicaClientV3, timestamp time.Time) (bool, error) {\n\t// Get v0.3.x time bounds.\n\t_, v3UpdatedAt, err := r.TimeBoundsV3(ctx, client)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"get v0.3.x time bounds: %w\", err)\n\t}\n\n\t// Get LTX time bounds.\n\t_, ltxUpdatedAt, err := r.TimeBounds(ctx)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"get LTX time bounds: %w\", err)\n\t}\n\n\t// If no v0.3.x backups exist, use LTX.\n\tif v3UpdatedAt.IsZero() {\n\t\treturn false, nil\n\t}\n\n\t// If no LTX backups exist, use v0.3.x.\n\tif ltxUpdatedAt.IsZero() {\n\t\tr.Logger().Debug(\"using v0.3.x restore (no LTX backups)\")\n\t\treturn true, nil\n\t}\n\n\t// Both formats have backups - compare based on timestamp or latest.\n\tif !timestamp.IsZero() {\n\t\t// With timestamp: use format with best snapshot before timestamp.\n\t\tv3Snapshot, err := r.findBestV3SnapshotForTimestamp(ctx, client, timestamp)\n\t\tif err != nil {","sourceCodeStart":1392,"sourceCodeEnd":1428,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/replica.go#L1392-L1428","documentation":"Wraps an error from TimeBounds while reading LTX-format time bounds during the v0.3.x vs LTX restore decision. Both formats' bounds are needed to pick the better restore source; failing to read the LTX bounds aborts the restore. The cause is the underlying client listing/manifest error.","triggerScenarios":"Restore -> shouldUseV3Restore -> TimeBounds(ctx) fails because the LTX replica data cannot be listed: missing/renamed replica path, storage outage, or corrupted LTX directory structure.","commonSituations":"Replica path misconfigured in the litestream.yml after a bucket migration; LTX files deleted by a lifecycle policy; object storage returning errors mid-listing.","solutions":["Check the wrapped cause and verify the LTX replica path in the config matches the actual storage layout.","Confirm object-store lifecycle rules have not deleted LTX files under generations/.","Retry on transient storage errors; use litestream reset only if local LTX state is corrupted (note it clears local LTX state).","If LTX data is gone intentionally, restore from the v0.3.x replica with an explicit restore target."],"exampleFix":"// before\n_, ltxUpdatedAt, err := r.TimeBounds(ctx)\nif err != nil {\n    return false, fmt.Errorf(\"get LTX time bounds: %w\", err)\n}\n// after\n// verify config points at the right replica path, then:\n_, ltxUpdatedAt, err := r.TimeBounds(ctx)\nif err != nil {\n    return false, fmt.Errorf(\"get LTX time bounds: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// confirm LTX replica path layout matches config before restore\n// storage bucket must contain generations/<gen>/... for the configured path\nif replicaPath == \"\" || !strings.HasPrefix(replicaPath, expectedPrefix) {\n    return fmt.Errorf(\"replica path mismatch\")\n}","typeGuard":null,"tryCatchPattern":"if err := restore(...); err != nil {\n    if strings.Contains(err.Error(), \"get LTX time bounds\") {\n        // check config replica path + lifecycle rules before retrying\n    }\n    return err\n}","preventionTips":["Keep replica paths in litestream.yml in sync with bucket renames/migrations.","Audit object-store lifecycle rules so they never delete LTX files mid-chain.","Disable built-in retention only when a cloud lifecycle policy handles cleanup."],"tags":["restore","ltx","time-bounds","storage-backend"],"backgroundTag":"api-request-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"}