{"record":{"id":"5ab2db5ae46f6029","repo":"thanos-io/thanos","slug":"read-range","errorCode":null,"errorMessage":"read range","messagePattern":"read range","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/store/bucket.go","lineNumber":2522,"sourceCode":"\nfunc (b *bucketBlock) indexFilename() string {\n\treturn path.Join(b.meta.ULID.String(), block.IndexFilename)\n}\n\nfunc (b *bucketBlock) readIndexRange(ctx context.Context, off, length int64, logger log.Logger) ([]byte, error) {\n\tr, err := b.bkt.GetRange(ctx, b.indexFilename(), off, length)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"get range reader\")\n\t}\n\tdefer runutil.CloseWithLogOnErr(logger, r, \"readIndexRange close range reader\")\n\n\t// Preallocate the buffer with the exact size so we don't waste allocations\n\t// while progressively growing an initial small buffer. The buffer capacity\n\t// is increased by MinRead to avoid extra allocations due to how ReadFrom()\n\t// internally works.\n\tbuf := bytes.NewBuffer(make([]byte, 0, length+bytes.MinRead))\n\tif _, err := buf.ReadFrom(r); err != nil {\n\t\treturn nil, errors.Wrap(err, \"read range\")\n\t}\n\treturn buf.Bytes(), nil\n}\n\nfunc (b *bucketBlock) readChunkRange(ctx context.Context, seq int, off, length int64, chunkRanges byteRanges, logger log.Logger) (*[]byte, error) {\n\tif seq < 0 || seq >= len(b.chunkObjs) {\n\t\treturn nil, errors.Errorf(\"unknown segment file for index %d\", seq)\n\t}\n\n\t// Get a reader for the required range.\n\treader, err := b.bkt.GetRange(ctx, b.chunkObjs[seq], off, length)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"get range reader\")\n\t}\n\tdefer runutil.CloseWithLogOnErr(logger, reader, \"readChunkRange close range reader\")\n\n\t// Get a buffer from the pool.\n\tchunkBuffer, err := b.chunkPool.Get(chunkRanges.size())","sourceCodeStart":2504,"sourceCodeEnd":2540,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/store/bucket.go#L2504-L2540","documentation":"This error wraps any failure that occurs while reading an object-storage byte range into an in-memory buffer inside bucketBlock.readAllChunks/readChunkRange helper. The store gateway fetched a range (e.g. a chunk file segment) via bkt.GetRange and then buffered it with bytes.Buffer.ReadFrom; if the underlying reader (S3/GCS/Azure/etc.) returns any I/O error mid-stream, it is wrapped with the message 'read range'. It is a transport-level failure, not a data-format problem.","triggerScenarios":"bucketBlock.readChunkRange/readAllChunks calls buf.ReadFrom(r) on a range reader from bkt.GetRange and the object store read fails mid-stream (connection reset, timeout, 5xx retried exhausted, truncated body).","commonSituations":"Object storage flakiness (S3 503 slow-down, GCS resets), network partitions between store-gateway and bucket, proxy/LB idle timeouts cutting long chunk downloads, over-aggressive object-store client timeouts.","solutions":["Inspect the wrapped inner error to identify the object-store client failure and fix root cause (credentials, bucket, endpoint).","Increase object-store client timeout/retry config in the bucket store config (http-client, retries on 5xx).","Verify network path to object storage (VPC endpoints, proxies, DNS) from the store-gateway pods.","Retry the query; Thanos retries bucket requests automatically a few times, transient errors often resolve."],"exampleFix":"// before\nbuf := bytes.NewBuffer(make([]byte, 0, length+bytes.MinRead))\nif _, err := buf.ReadFrom(r); err != nil {\n\treturn nil, errors.Wrap(err, \"read range\")\n}\n// after (caller side: bound the request with a context and let retries happen)\nctx, cancel := context.WithTimeout(ctx, 30*time.Second)\ndefer cancel()\nreader, err := b.bkt.GetRange(ctx, obj, off, length)\nif err != nil {\n\treturn nil, errors.Wrap(err, \"get range reader\")\n}","handlingStrategy":"retry","validationCode":"// ensure reader/context are bounded before use\nif r == nil { return errors.New(\"nil range reader\") }\nif _, ok := ctx.Deadline(); !ok {\n\tvar cancel context.CancelFunc\n\tctx, cancel = context.WithTimeout(ctx, 30*time.Second)\n\tdefer cancel()\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n\tvar netErr net.Error\n\tif errors.As(err, &netErr) && netErr.Timeout() {\n\t\t// retry with backoff\n\t}\n\treturn errors.Wrap(err, \"read range\")\n}","preventionTips":["Configure object-store client timeouts and retry limits in bucket store config","Monitor S3/GCS 5xx and throttling metrics","Keep store-gateway close to object storage (same region/VPC endpoint)"],"tags":["object-storage","io","network","thanos-store-gateway"],"backgroundTag":"http-request-failed","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}