{"record":{"id":"c29f4e78310c7cdf","repo":"thanos-io/thanos","slug":"read-postings-table","errorCode":null,"errorMessage":"read postings table","messagePattern":"read postings table","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/block/indexheader/binary_reader.go","lineNumber":719,"sourceCode":"\n\t\tvar prevRng index.Range\n\t\tif err := index.ReadPostingsOffsetTable(r.b, r.toc.PostingsOffsetTable, func(name, value []byte, postingsOffset uint64, _ int) error {\n\t\t\tif lastName != nil {\n\t\t\t\tprevRng.End = int64(postingsOffset - crc32.Size)\n\t\t\t\tr.postingsV1[string(lastName)][string(lastValue)] = prevRng\n\t\t\t}\n\n\t\t\tif _, ok := r.postingsV1[string(name)]; !ok {\n\t\t\t\tr.postingsV1[string(name)] = map[string]index.Range{}\n\t\t\t\tr.postings[string(name)] = nil // Used to get a list of labelnames in places.\n\t\t\t}\n\n\t\t\tlastName = name\n\t\t\tlastValue = value\n\t\t\tprevRng = index.Range{Start: int64(postingsOffset + postingLengthFieldSize)}\n\t\t\treturn nil\n\t\t}); err != nil {\n\t\t\treturn errors.Wrap(err, \"read postings table\")\n\t\t}\n\t\tif string(lastName) != \"\" {\n\t\t\tprevRng.End = r.indexLastPostingEnd - crc32.Size\n\t\t\tr.postingsV1[string(lastName)][string(lastValue)] = prevRng\n\t\t}\n\t} else {\n\t\tlastTableOff := 0\n\t\tvalueCount := 0\n\n\t\t// For the postings offset table we keep every label name but only every nth\n\t\t// label value (plus the first and last one), to save memory.\n\t\tif err := index.ReadPostingsOffsetTable(r.b, r.toc.PostingsOffsetTable, func(name, value []byte, postingsOffset uint64, labelOffset int) error {\n\t\t\tif _, ok := r.postings[string(name)]; !ok {\n\t\t\t\t// Not seen before label name.\n\t\t\t\tr.postings[string(name)] = &postingValueOffsets{}\n\t\t\t\tif lastName != nil {\n\t\t\t\t\t// Always include last value for each label name, unless it was just added in previous iteration based\n\t\t\t\t\t// on valueCount.","sourceCodeStart":701,"sourceCodeEnd":737,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/block/indexheader/binary_reader.go#L701-L737","documentation":"Wrapped error when index.ReadPostingsOffsetTable fails while loading the entire postings offset table for index FormatV1 blocks. The postings table section cannot be parsed, usually due to corruption or an offset pointing outside the valid region of the index file.","triggerScenarios":"Reading a FormatV1 index (which loads the whole postings offset table into memory) when the table bytes at toc.PostingsOffsetTable are malformed, truncated, or fail CRC checks.","commonSituations":"Legacy index-version-1 blocks read by newer Thanos; partially uploaded/downloaded index files; block corrupted during compaction or object-storage transfer.","solutions":["Re-upload or re-compact the affected block to repair the index file","Delete and rebuild the index-header file if the offsets are stale","Check the object storage for partial uploads and restore a complete block","Verify the block's meta.json and file sizes match what storage reports"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// pre-check: ensure index file size covers toc.PostingsOffsetTable range before reading","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"read postings table\") { delete index-header; retry with rebuilt header; else re-upload block }","preventionTips":["Use atomic block uploads (upload index last)","Run block verification (thanos tools bucket verify) periodically","Keep backups or object versioning for blocks"],"tags":["tsdb","index-header","postings","corruption"],"backgroundTag":"file-read-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"}