{"record":{"id":"1e77b50ab51eed50","repo":"thanos-io/thanos","slug":"open-index-reader-w","errorCode":null,"errorMessage":"open index reader: %w","messagePattern":"open index reader: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/receive/expandedpostingscache/tsdb.go","lineNumber":43,"sourceCode":"\tThis file is basically a copy from https://github.com/prometheus/prometheus/blob/e2e01c1cffbfc4f26f5e9fe6138af87d7ff16122/tsdb/querier.go\n\twith the difference that the PostingsForMatchers function is called from the Postings Cache\n*/\n\ntype blockBaseQuerier struct {\n\tblockID    ulid.ULID\n\tindex      prom_tsdb.IndexReader\n\tchunks     prom_tsdb.ChunkReader\n\ttombstones tombstones.Reader\n\n\tclosed bool\n\n\tmint, maxt int64\n}\n\nfunc newBlockBaseQuerier(b prom_tsdb.BlockReader, mint, maxt int64) (*blockBaseQuerier, error) {\n\tindexr, err := b.Index()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"open index reader: %w\", err)\n\t}\n\tchunkr, err := b.Chunks()\n\tif err != nil {\n\t\tindexr.Close()\n\t\treturn nil, fmt.Errorf(\"open chunk reader: %w\", err)\n\t}\n\ttombsr, err := b.Tombstones()\n\tif err != nil {\n\t\tindexr.Close()\n\t\tchunkr.Close()\n\t\treturn nil, fmt.Errorf(\"open tombstone reader: %w\", err)\n\t}\n\n\tif tombsr == nil {\n\t\ttombsr = tombstones.NewMemTombstones()\n\t}\n\treturn &blockBaseQuerier{\n\t\tblockID:    b.Meta().ULID,","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/receive/expandedpostingscache/tsdb.go#L25-L61","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check the wrapped %w error for the exact cause (e.g. 'invalid magic string', 'file not found')","Verify the block directory is intact; restore it from object storage or re-replicate the block","Raise the open-file limit (ulimit -n / systemd LimitNOFILE) if the cause is EMFILE","Restart/thanos-side repair: remove the corrupt block from local storage and let it be re-fetched"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if st, err := os.Stat(filepath.Join(blockDir, \"index\")); err != nil || st.IsDir() { return fmt.Errorf(\"block index missing: %w\", err) }","typeGuard":"func isIndexOpenErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"open index reader\")\n}","tryCatchPattern":"q, err := newBlockBaseQuerier(block, mint, maxt)\nif err != nil {\n    var pathErr *os.PathError\n    if errors.As(err, &pathErr) && errors.Is(pathErr, syscall.EMFILE) { /* raise fd limit / retry later */ }\n    return err\n}","preventionTips":["Verify block integrity before querying (manifest/checksum in object storage)","Raise RLIMIT_NOFILE for query-heavy deployments","Avoid deleting/compacting blocks while readers are open (use tsdb's block lifecycle)","Monitor disk health and free space on block storage volumes"],"tags":["tsdb","storage","query"],"backgroundTag":"file-open-failed","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}