thanos-io/thanos · error
reading postings
Error message
reading postings
What it means
After streaming the postings range through the postings reader (newPostingsReaderBuilder over a bufio.Reader), rdr.Error() reports any error accumulated while parsing the postings stream. This error means the ranged bytes from the index were read (or the underlying object-storage stream errored) but could not be fully parsed into postings.
Solutions
- Retry the query; transient stream errors are the most common cause
- Check query/store-gateway logs for context cancellation and increase query timeouts if applicable
- Validate the block (thanos tools bucket verify) — re-upload or delete the block if the index is corrupted
- Ensure the block is not modified/deleted while readers are using it (use deletion marks and proper block lifecycle)
Defensive patterns
Strategy: retry
Validate before calling
select {
case <-ctx.Done():
// abort before streaming: context already canceled
return ctx.Err()
default:
} Type guard
func isStreamErr(err error) bool { return errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) } Try / catch
if err := rdr.Error(); err != nil {
if isStreamErr(err) {
return retry.WithBackoff(ctx, func() error { return fetchPostingsRange(ctx, ptrs) })
}
return errors.Wrap(err, "reading postings")
} Prevention
- Set query timeouts comfortably above object-storage latencies
- Use stable network paths/VPC endpoints to the bucket
- Verify blocks before serving after failed uploads
- Retry idempotent ranged reads on transient stream errors
When it happens
Trigger: The object-storage range reader returned an error mid-stream (connection reset, context cancellation, timeout), or the postings binary data in the index range is corrupt/truncated so the diff-varint decoding fails while rdr iterates over ptrs[i:j].
Common situations: Unstable connection to S3/GCS causing mid-body stream failures; context canceled by client query timeout/cancellation; corrupted or partially uploaded index block; block replaced in the bucket while being read.
Related errors
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/b22e1c93db9782fa.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/store/bucket.go:3248
dataToCache, err := snappyStreamedEncode(int(postingsCount), diffVarintPostings)
if err != nil {
stats.cachedPostingsCompressionErrors += 1
return errors.Wrap(err, "encoding with snappy")
}
stats.cachedPostingsCompressions += 1
stats.CachedPostingsOriginalSizeSum += units.Base2Bytes(len(diffVarintPostings))
stats.CachedPostingsCompressedSizeSum += units.Base2Bytes(len(dataToCache))
stats.CachedPostingsCompressionTimeSum += time.Since(startCompression)
stats.add(PostingsTouched, 1, len(diffVarintPostings))
r.block.indexCache.StorePostings(r.block.meta.ULID, keys[keyID], dataToCache, tenant)
}
stats.PostingsFetchDurationSum += time.Since(begin)
if err := rdr.Error(); err != nil {
return errors.Wrap(err, "reading postings")
}
return nil
})
}
return output, closeFns, g.Wait()
}
func (r *bucketIndexReader) decodeCachedPostings(b []byte) (index.Postings, []func(), error) {
// Even if this instance is not using compression, there may be compressed
// entries in the cache written by other stores.
var (
l index.Postings
err error
closeFns []func()
)
if isDiffVarintSnappyEncodedPostings(b) || isDiffVarintSnappyStreamedEncodedPostings(b) {
s := time.Now()View on GitHub (pinned to 35b8b99117)