thanos-io/thanos · error
series
Error message
series
What it means
This error wraps a failure from IndexReader.Series(id, &builder, &chks) in block.Rewrite (pkg/block/index.go:615) while iterating each posting ID to rebuild series. It means the series section of the source index cannot be resolved for a specific series ID — the label set or chunk metas for that posting are unreadable. Because rewrite iterates every posting, a single corrupt series entry fails the whole rewrite.
Solutions
- Identify the failing series ID from the wrapped inner error; if isolated, use promtool tsdb analyze or drop/rewrite the specific block.
- Restore the block from backup or another replica; individual corrupt series entries generally cannot be repaired in place.
- Quarantine (move out) the corrupt block so TSDB marks it and continues operating; re-fetch the affected time range from remote storage.
- If many series fail, treat the whole index as corrupt and prefer full block re-download over Repair.
Example fix
// before: one bad series aborts entire repair
if err := indexr.Series(id, &builder, &chks); err != nil { return errors.Wrap(err, "series") }
// after: tolerate isolated failures during repair by skipping bad IDs
if err := indexr.Series(id, &builder, &chks); err != nil {
log.Warn("skipping unreadable series in rewrite", "id", id, "err", err)
continue
} Defensive patterns
Strategy: try-catch
Validate before calling
all, err := indexr.Postings(ctx, index.AllPostingsKey())
if err != nil { return err }
it := indexr.SortedPostings(all)
for it.Next() { if _, err := indexr.Series(it.At()); err != nil { log.Warn("unreadable series", "id", it.At()) } } Type guard
func isSeriesError(err error) bool { return err != nil && strings.Contains(err.Error(), "series") } Try / catch
if err := block.Rewrite(ctx, meta, src, dst, indexr, chunkr, nil); err != nil {
var seriesErr bool
if strings.Contains(err.Error(), "series") { seriesErr = true }
if seriesErr { /* identify failing id from wrapped cause, skip or restore block */ }
return err
} Prevention
- Log the failing posting ID (available in the wrapped cause) to scope corruption
- For repair tooling, consider skipping isolated unreadable series instead of failing the whole rewrite
- Restore from replicas rather than repeatedly rewriting blocks with corrupt series sections
When it happens
Trigger: For a given posting ID from the all-postings iterator, indexr.Series() fails decoding the label builder or chunk metadata (bad offset into the series section, invalid varint, out-of-range reference).
Common situations: Repairing blocks where individual series entries were corrupted by crash/incomplete write; blocks after disk errors; partially recovered block directories where index sections reference each other inconsistently.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/4c5c045c7f7892c2.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/block/index.go:615
return errors.Wrap(err, "postings")
}
all = indexr.SortedPostings(all)
// We fully rebuild the postings list index from merged series.
var (
postings = index.NewMemPostings()
values = map[string]stringset{}
i = storage.SeriesRef(0)
series = []seriesRepair{}
)
var builder labels.ScratchBuilder
var chks []chunks.Meta
for all.Next() {
id := all.At()
if err := indexr.Series(id, &builder, &chks); err != nil {
return errors.Wrap(err, "series")
}
// Make sure labels are in sorted order.
builder.Sort()
for i, c := range chks {
// Ignore iterable as it should be nil.
chks[i].Chunk, _, err = chunkr.ChunkOrIterable(c)
if err != nil {
return errors.Wrap(err, "chunk read")
}
}
chks, err := sanitizeChunkSequence(chks, meta.MinTime, meta.MaxTime, ignoreChkFns)
if err != nil {
return err
}
if len(chks) == 0 {View on GitHub (pinned to 35b8b99117)