thanos-io/thanos · error
empty label set detected for series
Error message
empty label set detected for series %d
What it means
GatherIndexHealthStats detects a series whose decoded label set is empty (no labels at all). Since every TSDB series must have at least a __name__ label, this is a hard invariant violation indicating a corrupt or malformed index. The error message includes the offending series reference ID.
Solutions
- Treat the block as corrupt; restore it from object storage or backup
- Identify the offending series ref from the error message to confirm offset corruption
- Re-run offline compaction to rebuild the index if chunk data is intact
- Delete the block so it is re-fetched or tombstoned
Example fix
// before
stats, err := block.GatherIndexHealthStats(ctx, bdir) // empty label set detected for series 12345
// after
meta, err := metadata.ReadFromDir(bdir)
if err != nil { return err }
if _, err := block.Repair(ctx, logger, filepath.Dir(bdir), meta.ULID, meta.Thanos.Source); err != nil {
return fmt.Errorf("block %s unusable, remove manually: %w", meta.ULID, err)
} Defensive patterns
Strategy: validation
Validate before calling
if err := block.VerifyIndex(ctx, bdir, 1); err != nil {
return fmt.Errorf("block %s failed index verification: %w", bdir, err)
} Try / catch
stats, err := block.GatherIndexHealthStats(ctx, bdir)
var emptyLsetErr *errors.errorString
if err != nil && strings.Contains(err.Error(), "empty label set detected") {
return block.Repair(ctx, logger, filepath.Dir(bdir), id, source, block.IgnoreIssue347OutsideChunks)
} Prevention
- Check block health before repair/downsampling operations
- Restore from verified backups when index invariants fail
- Track known historical TSDB index bugs for blocks written by old versions
- Tombstone irreparable blocks quickly to keep store-gateway healthy
When it happens
Trigger: r.Series(id, ...) decodes successfully but yields an empty label set — typically a damaged series section, mispadded offsets (v2 index 16-byte padding), or an index written by buggy code.
Common situations: Blocks affected by historical TSDB index bugs, corrupted uploads, blocks whose index was partially overwritten, forensic verification after storage incidents.
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
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/ddb7027f72df73e8.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/block/index.go:283
// Per series.
var prevId storage.SeriesRef
for p.Next() {
prevLset.CopyFrom(lset)
id := p.At()
if prevId != 0 {
// Approximate size.
seriesSize.Add(int64(id-prevId) * int64(offsetMultiplier))
}
prevId = id
stats.TotalSeries++
if err := r.Series(id, &builder, &chks); err != nil {
return stats, errors.Wrap(err, "read series")
}
lset = builder.Labels()
if lset.IsEmpty() {
return stats, errors.Errorf("empty label set detected for series %d", id)
}
if !prevLset.IsEmpty() && labels.Compare(prevLset, lset) >= 0 {
return stats, errors.Errorf("series %v out of order; previous %v", lset, prevLset)
}
var l0 *labels.Label
lset.Range(func(l labels.Label) {
if l0 != nil {
if l.Name < l0.Name {
stats.OutOfOrderLabels++
level.Warn(logger).Log("msg",
"out-of-order label set: known bug in Prometheus 2.8.0 and below",
"labelset", lset.String(),
"series", fmt.Sprintf("%d", id),
)
}
}
l0 = &l
})View on GitHub (pinned to 35b8b99117)