thanos-io/thanos · error

open index reader

Error message

open index reader: %w

What it means

newBlockBaseQuerier opens a TSDB block's index reader via BlockReader.Index() and wraps any failure as 'open index reader: %w'. This happens when the block's index cannot be opened, typically due to corrupted block files, missing index segments, or I/O errors. The wrapped error from the Prometheus tsdb package carries the root cause.

Solutions

  1. Check the wrapped %w error for the exact cause (e.g. 'invalid magic string', 'file not found')
  2. Verify the block directory is intact; restore it from object storage or re-replicate the block
  3. Raise the open-file limit (ulimit -n / systemd LimitNOFILE) if the cause is EMFILE
  4. Restart/thanos-side repair: remove the corrupt block from local storage and let it be re-fetched
Defensive patterns

Strategy: retry

Validate before calling

if st, err := os.Stat(filepath.Join(blockDir, "index")); err != nil || st.IsDir() { return fmt.Errorf("block index missing: %w", err) }

Type guard

func isIndexOpenErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "open index reader")
}

Try / catch

q, err := newBlockBaseQuerier(block, mint, maxt)
if err != nil {
    var pathErr *os.PathError
    if errors.As(err, &pathErr) && errors.Is(pathErr, syscall.EMFILE) { /* raise fd limit / retry later */ }
    return err
}

Prevention

When it happens

Trigger: newBlockBaseQuerier is invoked by NewCachedBlockChunkQuerier when a cached block querier is created; b.Index() fails for a block being read from disk (corrupt/mismatched index file, block directory incomplete, too many open files).

Common situations: Thanos receive storing blocks locally while a compaction/upload races with a query, disk corruption or partial block download, EMFILE (too many open files) under heavy query load, querying a block directory that was removed mid-query.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at pkg/receive/expandedpostingscache/tsdb.go:43

	This file is basically a copy from https://github.com/prometheus/prometheus/blob/e2e01c1cffbfc4f26f5e9fe6138af87d7ff16122/tsdb/querier.go
	with the difference that the PostingsForMatchers function is called from the Postings Cache
*/

type blockBaseQuerier struct {
	blockID    ulid.ULID
	index      prom_tsdb.IndexReader
	chunks     prom_tsdb.ChunkReader
	tombstones tombstones.Reader

	closed bool

	mint, maxt int64
}

func newBlockBaseQuerier(b prom_tsdb.BlockReader, mint, maxt int64) (*blockBaseQuerier, error) {
	indexr, err := b.Index()
	if err != nil {
		return nil, fmt.Errorf("open index reader: %w", err)
	}
	chunkr, err := b.Chunks()
	if err != nil {
		indexr.Close()
		return nil, fmt.Errorf("open chunk reader: %w", err)
	}
	tombsr, err := b.Tombstones()
	if err != nil {
		indexr.Close()
		chunkr.Close()
		return nil, fmt.Errorf("open tombstone reader: %w", err)
	}

	if tombsr == nil {
		tombsr = tombstones.NewMemTombstones()
	}
	return &blockBaseQuerier{
		blockID:    b.Meta().ULID,

View on GitHub (pinned to 35b8b99117)