{"record":{"id":"57e9ddab4aa70b0f","repo":"benbjohnson/litestream","slug":"fetch-l1-files-w-57e9dd","errorCode":null,"errorMessage":"fetch l1 files: %w","messagePattern":"fetch l1 files: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":3031,"sourceCode":"\n\treturn minSnapshotTXID, nil\n}\n\n// EnforceL0RetentionByTime retains L0 files until they have been compacted into\n// L1 and have existed for at least L0Retention.\nfunc (db *DB) EnforceL0RetentionByTime(ctx context.Context) error {\n\tif db.L0Retention <= 0 {\n\t\treturn nil\n\t}\n\n\tdb.Logger.Debug(\"starting l0 retention enforcement\", \"retention\", db.L0Retention)\n\n\tdbName := filepath.Base(db.Path())\n\n\t// Determine the highest TXID that has been compacted into L1.\n\titr, err := db.Replica.Client.LTXFiles(ctx, 1, 0, false)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fetch l1 files: %w\", err)\n\t}\n\tvar maxL1TXID ltx.TXID\n\tfor itr.Next() {\n\t\tinfo := itr.Item()\n\t\tif info.MaxTXID > maxL1TXID {\n\t\t\tmaxL1TXID = info.MaxTXID\n\t\t}\n\t}\n\tif err := itr.Close(); err != nil {\n\t\treturn fmt.Errorf(\"close l1 iterator: %w\", err)\n\t}\n\tif maxL1TXID == 0 {\n\t\tinternal.L0RetentionGaugeVec.WithLabelValues(dbName, \"eligible\").Set(0)\n\t\tinternal.L0RetentionGaugeVec.WithLabelValues(dbName, \"not_compacted\").Set(0)\n\t\tinternal.L0RetentionGaugeVec.WithLabelValues(dbName, \"too_recent\").Set(0)\n\t\treturn nil\n\t}\n","sourceCodeStart":3013,"sourceCodeEnd":3049,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L3013-L3049","documentation":"Wraps a failure from Replica.Client.LTXFiles when listing level-1 (L1) compacted files to determine the highest compacted TXID during L0 retention processing. The listing must succeed to know whether L0 files can be safely removed, so the error aborts the operation.","triggerScenarios":"Running L0 retention enforcement when the remote L1 listing fails: storage outage, bad credentials, DNS failure, or a misconfigured replica endpoint (db.go:3031).","commonSituations":"Periodic compaction/retention job running while the object store is down; expired IAM credentials; unreachable S3/GS endpoint from a VPC.","solutions":["Test bucket access with the provider CLI using the same credentials.","Read the wrapped inner error to distinguish auth vs network vs not-found.","Retry after connectivity is restored; the listing is read-only.","Verify replica config (endpoint, region, bucket) especially for S3-compatible providers."],"exampleFix":"// caller-side retry around the retention pass\nif err := enforceL0Retention(ctx, db); err != nil && isTransient(err) {\n    time.Sleep(backoff)\n    err = enforceL0Retention(ctx, db)\n}","handlingStrategy":"retry","validationCode":"if err := db.Replica.Client.Init(ctx); err != nil { return fmt.Errorf(\"replica init failed: %w\", err) }","typeGuard":null,"tryCatchPattern":"itr, err := db.Replica.Client.LTXFiles(ctx, 1, 0, false)\nif err != nil {\n    if isTransient(err) { return retryWithBackoff(ctx) }\n    return fmt.Errorf(\"fetch l1 files: %w\", err)\n}","preventionTips":["Verify endpoint/region/bucket settings for S3-compatible providers.","Automate credential rotation before expiry.","Run retention jobs with retry/backoff."],"tags":["storage","compaction","retention","network"],"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"}