{"record":{"id":"7efc63331f8968ea","repo":"benbjohnson/litestream","slug":"ltx-files-w","errorCode":null,"errorMessage":"ltx files: %w","messagePattern":"ltx files: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vfs.go","lineNumber":2722,"sourceCode":"\tf.maxTXID1 = maxTXID1\n\tf.logger.Debug(\"txid updated\", \"txid\", f.pos.TXID.String(), \"maxTXID1\", f.maxTXID1.String())\n\n\t// Apply updates to hydrated file if hydration is complete\n\tif f.hydrator != nil && f.hydrator.Complete() && len(combined) > 0 {\n\t\tif err := f.hydrator.ApplyUpdates(f.ctx, combined); err != nil {\n\t\t\tf.logger.Error(\"failed to apply updates to hydrated file\", \"error\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// pollLevel fetches LTX files for a specific level and returns the highest TXID seen,\n// any index updates, the latest commit value, and if the index should be replaced.\nfunc (f *VFSFile) pollLevel(ctx context.Context, level int, prevMaxTXID ltx.TXID, baseCommit uint32) (ltx.TXID, map[uint32]ltx.PageIndexElem, uint32, bool, error) {\n\titr, err := f.client.LTXFiles(ctx, level, prevMaxTXID+1, false)\n\tif err != nil {\n\t\treturn prevMaxTXID, nil, baseCommit, false, fmt.Errorf(\"ltx files: %w\", err)\n\t}\n\tdefer func() { _ = itr.Close() }()\n\n\tindex := make(map[uint32]ltx.PageIndexElem)\n\tmaxTXID := prevMaxTXID\n\tlastCommit := baseCommit\n\tnewCommit := baseCommit\n\treplaceIndex := false\n\n\tfor itr.Next() {\n\t\tinfo := itr.Item()\n\n\t\tf.mu.Lock()\n\t\tisNextTXID := info.MinTXID == maxTXID+1\n\t\tf.mu.Unlock()\n\t\tif !isNextTXID {\n\t\t\tif level == 0 && info.MinTXID > maxTXID+1 {\n\t\t\t\tf.logger.Warn(\"ltx gap detected at L0, deferring to higher levels\", \"expected\", maxTXID+1, \"next\", info.MinTXID)","sourceCodeStart":2704,"sourceCodeEnd":2740,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L2704-L2740","documentation":"Wraps failure fetching LTX files for a level in VFSFile.pollLevel, which polls the replica for new files to update the virtual file's index. Fires when the replica client's LTXFiles call errors during a poll cycle, so level updates cannot proceed.","triggerScenarios":"Any failure from the ReplicaClient's LTXFiles listing API: network errors, HTTP error responses from S3/GCS/Azure, invalid credentials, or unsupported client implementations.","commonSituations":"Expired cloud credentials mid-run; region/endpoint misconfiguration; object storage throttling (5xx / SlowDown); VPC without egress to the storage endpoint.","solutions":["Read the wrapped error for the concrete client failure","Validate credentials and bucket configuration for the replica client","Check for storage provider throttling and add backoff/retry at the client level","Run `litestream reset` if local replicated state is corrupted after repeated failures"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// verify list access before opening VFS\nitr, err := replicaClient.LTXFiles(context.Background(), 0, 1, false)\nif err != nil { return fmt.Errorf(\"cannot list replica: %w\", err) }\nitr.Close()","typeGuard":null,"tryCatchPattern":"itr, err := client.LTXFiles(ctx, level, minTXID, false)\nif err != nil {\n    if isRetryablePageError(err) { return retryAfterBackoff() }\n    return fmt.Errorf(\"ltx files: %w\", err)\n}","preventionTips":["Validate replica client config at startup","Set generous timeouts for object storage clients","Handle provider 5xx/SlowDown with exponential backoff"],"tags":["storage","replica-client","list-files"],"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"}