thanos-io/thanos · error

cannot populate block from no readers

Error message

cannot populate block from no readers

What it means

compactSeries refuses to operate on zero series readers and returns a sentinel error "cannot populate block from no readers". Like WriteSeries' empty-readers check, this is an internal fail-fast guard: merging zero sources would produce an empty block.

Solutions

  1. Check len(sReaders) before calling compactSeries and handle the empty case at the call site
  2. If called from custom code, route through WriteSeries which validates inputs first
  3. Fix upstream logic that builds the reader list so it never produces zero readers for a real compaction

Example fix

// before
symbols, set, err := compactSeries(ctx, sReaders...)
// after
if len(sReaders) == 0 {
    return nil
}
symbols, set, err := compactSeries(ctx, sReaders...)
Defensive patterns

Strategy: validation

Validate before calling

if len(sReaders) == 0 {
    return nil, nil, nil // or skip compaction entirely
}
symbols, set, err := compactSeries(ctx, sReaders...)

Prevention

When it happens

Trigger: Calling compactSeries directly with no readers; unreachable via WriteSeries in practice because WriteSeries pre-validates len(readers) > 0.

Common situations: Tests or custom tooling that call compactSeries directly with a dynamically built reader list that ended up empty; refactoring that bypasses the WriteSeries guard.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/47afce6cdbfd08c0. Report an issue: GitHub.

Appendix: source

Thrown at pkg/compactv2/compactor.go:157

			}
			p.SeriesProcessed()
		}
		if err := set.Err(); err != nil {
			level.Error(w.logger).Log("msg", "error while iterating over set", "err", err)
		}
		return nil
	}

	if err := w.write(ctx, symbols, set, sWriter, p); err != nil {
		return errors.Wrap(err, "write")
	}
	return nil
}

// compactSeries compacts blocks' series into symbols and one ChunkSeriesSet with lazy populating chunks.
func compactSeries(ctx context.Context, sReaders ...seriesReader) (symbols index.StringIter, set storage.ChunkSeriesSet, _ error) {
	if len(sReaders) == 0 {
		return nil, nil, errors.New("cannot populate block from no readers")
	}

	var sets []storage.ChunkSeriesSet
	for i, r := range sReaders {
		select {
		case <-ctx.Done():
			return nil, nil, ctx.Err()
		default:
		}

		k, v := index.AllPostingsKey()
		all, err := r.ir.Postings(ctx, k, v)
		if err != nil {
			return nil, nil, err
		}
		all = r.ir.SortedPostings(all)
		syms := r.ir.Symbols()
		sets = append(sets, newLazyPopulateChunkSeriesSet(r, all))

View on GitHub (pinned to 35b8b99117)