thanos-io/thanos · error
read series range
Error message
read series range
What it means
Loading series (Series/Lookup) fetches a byte range of the block index via r.block.readIndexRange, which may consult cache or do a ranged object-storage GET. This error wraps any failure fetching that byte range — cache miss failure, object missing, network error, or throttling — for the requested series ids range.
Solutions
- Retry the query; verify whether the error is transient (network/throttle) or persistent (missing object)
- Check that the block and its index still exist in the bucket and is not deleted mid-query
- Inspect and fix the series cache backend configuration, or clear corrupted cache entries
- Look at the wrapped error to distinguish permission issues (fix IAM) from network issues (fix connectivity)
Defensive patterns
Strategy: retry
Validate before calling
if end <= start || uint64(end) > indexFileSize {
// invalid range: do not call readIndexRange
} Type guard
func validRange(start, end uint64, size uint64) bool { return start < end && end <= size } Try / catch
b, err := r.block.readIndexRange(ctx, int64(start), int64(end-start), r.logger)
if err != nil {
if isTransient(err) {
b, err = retryFetch(ctx, start, end)
}
if err != nil { return errors.Wrap(err, "read series range") }
} Prevention
- Tune series cache to avoid stale/corrupt entries
- Configure bucket retries/backoff for throttling
- Check index object existence before large fan-out reads
- Alert on seriesRefetches and fetch error rates
When it happens
Trigger: r.block.readIndexRange(ctx, start, end-start, logger) fails during LoadSeries: object-storage ranged GET error, series cache (store.index-cache.series) fetch error, or context cancellation while fetching.
Common situations: Heavy series fan-out queries exceeding bucket request rate limits; index object deleted while being read; misconfigured or unavailable external series cache; network timeouts on large ranges.
Related errors
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/f61910050905ea38.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/store/bucket.go:3399
})
}
return g.Wait()
}
func (r *bucketIndexReader) loadSeries(ctx context.Context, ids []storage.SeriesRef, refetch bool, start, end uint64, bytesLimiter BytesLimiter, tenant string) error {
begin := time.Now()
stats := new(queryStats)
defer func() {
r.stats.merge(stats)
}()
if err := bytesLimiter.ReserveWithType(uint64(end-start), SeriesFetched); err != nil {
return httpgrpc.Errorf(int(codes.ResourceExhausted), "exceeded bytes limit while fetching series: %s", err)
}
b, err := r.block.readIndexRange(ctx, int64(start), int64(end-start), r.logger)
if err != nil {
return errors.Wrap(err, "read series range")
}
stats.seriesFetchCount++
stats.SeriesFetchDurationSum += time.Since(begin)
stats.add(SeriesFetched, len(ids), int(end-start))
for i, id := range ids {
c := b[uint64(id)-start:]
l, n := binary.Uvarint(c)
if n < 1 {
return errors.New("reading series length failed")
}
if len(c) < n+int(l) {
if i == 0 && refetch {
return errors.Errorf("invalid remaining size, even after refetch, remaining: %d, expected %d", len(c), n+int(l))
}
View on GitHub (pinned to 35b8b99117)