{"record":{"id":"f3eea4ce5af7fad4","repo":"benbjohnson/litestream","slug":"list-wal-segments-w","errorCode":null,"errorMessage":"list WAL segments: %w","messagePattern":"list WAL segments: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"replica.go","lineNumber":1126,"sourceCode":"\n\t// Sort all snapshots by CreatedAt for timestamp-based selection.\n\tsortSnapshotsV3ByCreatedAt(allSnapshots)\n\n\t// Find best snapshot across all generations (latest, or before timestamp if specified).\n\tsnapshot := findBestSnapshotV3(allSnapshots, opt.Timestamp)\n\tif snapshot == nil {\n\t\treturn ErrNoSnapshots\n\t}\n\n\tr.Logger().Debug(\"selected v0.3.x snapshot\",\n\t\t\"generation\", snapshot.Generation,\n\t\t\"index\", snapshot.Index,\n\t\t\"created_at\", snapshot.CreatedAt)\n\n\t// Get WAL segments for the snapshot's generation.\n\tsegments, err := client.WALSegmentsV3(ctx, snapshot.Generation)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"list WAL segments: %w\", err)\n\t}\n\tsegments = filterWALSegmentsV3(segments, snapshot.Index, opt.Timestamp)\n\n\tr.Logger().Debug(\"found v0.3.x WAL segments\", \"n\", len(segments))\n\n\t// Create parent directory if it doesn't exist.\n\tvar dirInfo os.FileInfo\n\tif db := r.DB(); db != nil {\n\t\tdirInfo = db.DirInfo()\n\t}\n\tif err := internal.MkdirAll(filepath.Dir(opt.OutputPath), dirInfo); err != nil {\n\t\treturn fmt.Errorf(\"create parent directory: %w\", err)\n\t}\n\n\t// Create temp file for restore.\n\ttmpPath := opt.OutputPath + \".tmp\"\n\tdefer func() { _ = os.Remove(tmpPath) }()\n","sourceCodeStart":1108,"sourceCodeEnd":1144,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/replica.go#L1108-L1144","documentation":"After selecting a snapshot, RestoreV3 fetches the WAL segment list for the snapshot's generation via client.WALSegmentsV3(ctx, snapshot.Generation); any backend error is wrapped as 'list WAL segments: %w'. WAL segments are needed to roll the snapshot forward to the latest transaction or requested timestamp.","triggerScenarios":"Calling Replica.Restore when listing WAL objects fails — backend unreachable, wrong credentials, missing/g deleted WAL prefix for the selected generation, throttled list requests, or the storage layout is not v0.3.x compatible.","commonSituations":"WAL retention/lifecycle rules in the bucket deleted the WAL prefix while snapshots remain; S3 permissions differing between snapshot and WAL prefixes; network outage mid-restore; pointing at a bucket written by a different litestream version with an unexpected layout.","solutions":["Inspect the wrapped cause for the specific storage error (auth, 404, timeout) and fix it","Verify the WAL directory/prefix still exists in the snapshot's generation in the replica storage","Check bucket lifecycle policies are not deleting WAL segments prematurely","Retry the restore; listing is read-only and safe to repeat"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight: WAL prefix must exist for the generation you expect to restore from\nif _, err := client.WALSegmentsV3(ctx, generation); err != nil {\n    return fmt.Errorf(\"WAL listing failed: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := replica.Restore(ctx, opt); err != nil {\n    if strings.Contains(err.Error(), \"list WAL segments\") {\n        log.Printf(\"WAL listing failed, cause=%v\", errors.Unwrap(err))\n        return retryWithBackoff(ctx, 3, func() error { return replica.Restore(ctx, opt) })\n    }\n    return err\n}","preventionTips":["Check bucket lifecycle rules so WAL segments are not deleted before snapshots expire","Grant the replica client credentials read access to both snapshot and WAL prefixes","Keep litestream version consistent between writer and restore tooling to avoid layout mismatches","Include WAL listing in pre-restore health checks"],"tags":["go","restore","wal","storage","s3"],"backgroundTag":"http-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"}