{"record":{"id":"e7b2fce7ad4c834f","repo":"thanos-io/thanos","slug":"header-not-found","errorCode":null,"errorMessage":"header not found","messagePattern":"header not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/store/postings_codec.go","lineNumber":136,"sourceCode":"\t\t} else if written != uvarintSize {\n\t\t\treturn nil, errors.Wrap(err, \"short-write for uvarint encoded byte\")\n\t\t}\n\n\t\tprev = v\n\t}\n\tif p.Err() != nil {\n\t\treturn nil, p.Err()\n\t}\n\tif err := sw.Close(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"closing snappy stream writer\")\n\t}\n\n\treturn compressedBuf.Bytes(), nil\n}\n\nfunc diffVarintSnappyStreamedDecode(input []byte, disablePooling bool) (closeablePostings, error) {\n\tif !isDiffVarintSnappyStreamedEncodedPostings(input) {\n\t\treturn nil, errors.New(\"header not found\")\n\t}\n\n\treturn newStreamedDiffVarintPostings(input[len(codecHeaderStreamedSnappy):], disablePooling)\n}\n\ntype streamedDiffVarintPostings struct {\n\tcurSeries storage.SeriesRef\n\n\terr               error\n\tinput, buf        []byte\n\tmaximumDecodedLen int\n\n\tdb *encoding.Decbuf\n\n\treadSnappyIdentifier bool\n\tdisablePooling       bool\n}\n","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/store/postings_codec.go#L118-L154","documentation":"A generic guard in the decoder: the input bytes do not start with the streamed-snappy codec magic header (codecHeaderStreamedSnappy), so diffVarintSnappyStreamedDecode refuses the input. Either the data is not encoded postings at all, or it was written by an older Thanos using the non-streamed codec variant.","triggerScenarios":"Calling diffVarintSnappyStreamedDecode (via decodePostings) with input failing isDiffVarintSnappyStreamedEncodedPostings — wrong decoder dispatch, truncated header, or non-streamed codec bytes.","commonSituations":"Version mismatch between cache writer and reader; hand-crafted or corrupted cache entries; truncation of the first bytes of a postings blob.","solutions":["Verify the input begins with the expected codecHeaderStreamedSnappy bytes before decoding","Purge/rebuild the affected postings cache entries","Check writer/reader Prometheus version compatibility"],"exampleFix":"// before\nd, err := diffVarintSnappyStreamedDecode(b, false)\n// after\nif !isDiffVarintSnappyStreamedEncodedPostings(b) {\n    return fmt.Errorf(\"not streamed snappy postings, len=%d\", len(b))\n}\nd, err := diffVarintSnappyStreamedDecode(b, false)","handlingStrategy":"validation","validationCode":"func isStreamedSnappyPostings(b []byte) bool {\n    return bytes.HasPrefix(b, codecHeaderStreamedSnappy)\n}","typeGuard":"func asStreamedSnappyPostings(b []byte) ([]byte, bool) {\n    if !bytes.HasPrefix(b, codecHeaderStreamedSnappy) { return nil, false }\n    return b[len(codecHeaderStreamedSnappy):], true\n}","tryCatchPattern":"p, err := diffVarintSnappyStreamedDecode(b, false)\nif err != nil {\n    if err.Error() == \"header not found\" {\n        return nil, errCorruptCacheEntry // evict and refetch from index\n    }\n    return nil, err\n}","preventionTips":["Dispatch decoders only after checking the magic header (as decodePostings does)","Purge cache entries with missing/truncated headers","Keep writer and reader Prometheus versions compatible"],"tags":["postings","snappy","corruption"],"backgroundTag":"checksum-mismatch","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"}