thanos-io/thanos · error
got empty chunks
Error message
got empty chunks
What it means
newChunkSeriesIterator requires at least one chunk iterator to construct a chunkSeriesIterator; it is an internal invariant that callers pass a non-empty slice. An empty slice indicates an upstream bug where zero chunk iterators were collected.
Solutions
- Report/inspect the calling code path — this signals an internal invariant violation, not user error
- Check store responses for empty series data and verify store health
- Upgrade Thanos to the latest patch release
- File an issue with the query and store logs if reproducible
Defensive patterns
Strategy: try-catch
Try / catch
if err := ss.Err(); err != nil {
if strings.Contains(err.Error(), "got empty chunks") {
return storage.EmptySeriesSet(), nil // internal bug; degrade gracefully
}
return err
} Prevention
- Keep Thanos patched to the latest release
- Monitor for this error — report it upstream as an invariant violation
- Avoid custom forks/patches around chunk iterator construction
When it happens
Trigger: Calling newChunkSeriesIterator with a nil/empty []chunkenc.Iterator, which happens only due to an internal defect in how Iterator assembles chunk iterators per series.
Common situations: Encountered as a symptom of a Thanos engine bug, usually alongside concurrent store failures or malformed series responses; rarely caused by user configuration.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- unexpected result aggregate type
- no valid chunk found
- unknown partial response strategy
- add thanos opts query params
- failed to wait for turn
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/0746e069a6550c1b.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/query/iter.go:227
func (errSeriesIterator) AtFloatHistogram(*histogram.FloatHistogram) (int64, *histogram.FloatHistogram) {
return 0, nil
}
func (errSeriesIterator) AtT() int64 { return 0 }
func (it errSeriesIterator) Err() error { return it.err }
// chunkSeriesIterator implements a series iterator on top
// of a list of time-sorted, non-overlapping chunks.
type chunkSeriesIterator struct {
chunks []chunkenc.Iterator
i int
lastVal chunkenc.ValueType
cur chunkenc.Iterator
}
func newChunkSeriesIterator(cs []chunkenc.Iterator) chunkenc.Iterator {
if len(cs) == 0 {
return errSeriesIterator{err: errors.New("got empty chunks")}
}
return &chunkSeriesIterator{chunks: cs, cur: cs[0]}
}
func (it *chunkSeriesIterator) Seek(t int64) chunkenc.ValueType {
// We generally expect the chunks already to be cut down
// to the range we are interested in. There's not much to be gained from
// hopping across chunks so we just call next until we reach t.
for {
ct := it.AtT()
if ct >= t {
return it.lastVal
}
it.lastVal = it.Next()
if it.lastVal == chunkenc.ValNone {
return chunkenc.ValNone
}
}View on GitHub (pinned to 35b8b99117)