{"record":{"id":"f72526e32f7928fd","repo":"thanos-io/thanos","slug":"unknown-chunk-encoding","errorCode":null,"errorMessage":"unknown chunk encoding","messagePattern":"unknown chunk encoding","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/store/bucket.go","lineNumber":1499,"sourceCode":"\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tout.Counter = &storepb.Chunk{Type: chunkToStoreEncoding(x.Encoding()), Data: b, Hash: hashChunk(hasher, b, calculateChecksum)}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc chunkToStoreEncoding(in chunkenc.Encoding) storepb.Chunk_Encoding {\n\tswitch in {\n\tcase chunkenc.EncXOR:\n\t\treturn storepb.Chunk_XOR\n\tcase chunkenc.EncHistogram:\n\t\treturn storepb.Chunk_HISTOGRAM\n\tcase chunkenc.EncFloatHistogram:\n\t\treturn storepb.Chunk_FLOAT_HISTOGRAM\n\tdefault:\n\t\tpanic(\"unknown chunk encoding\")\n\t}\n}\n\nfunc hashChunk(hasher hash.Hash64, b []byte, doHash bool) uint64 {\n\tif !doHash {\n\t\treturn 0\n\t}\n\thasher.Reset()\n\t// Write never returns an error on the hasher implementation\n\t_, _ = hasher.Write(b)\n\treturn hasher.Sum64()\n}\n\n// debugFoundBlockSetOverview logs on debug level what exactly blocks we used for query in terms of\n// labels and resolution. This is important because we allow mixed resolution results, so it is quite crucial\n// to be aware what exactly resolution we see on query.\n// TODO(bplotka): Consider adding resolution label to all results to propagate that info to UI and Query API.\nfunc debugFoundBlockSetOverview(logger log.Logger, mint, maxt, maxResolutionMillis int64, lset labels.Labels, bs []*bucketBlock) {","sourceCodeStart":1481,"sourceCodeEnd":1517,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/store/bucket.go#L1481-L1517","documentation":"chunkToStoreEncoding maps Prometheus chunkenc encodings to storepb chunk types. When handed an encoding it does not recognize (not XOR, HISTOGRAM, or FLOAT_HISTOGRAM — e.g. the EncAggr aggregate container), it panics. This is an internal invariant: the function assumes it is only ever called on plain data chunks, never aggregate containers.","triggerScenarios":"Code path calls chunkToStoreEncoding on a chunk whose Encoding() is not one of chunkenc.EncXOR, EncHistogram, or EncFloatHistogram — e.g. an AggrChunk (EncAggr) leaked into the per-aggregate save path, or a new Prometheus chunk encoding appears without updating this switch.","commonSituations":"Thanos/Prometheus version skew introducing a new chunk encoding; regression in the downsample serving path passing the AggrChunk itself instead of a sub-chunk; custom forks adding encodings without updating the store mapping.","solutions":["Check the Thanos and Prometheus client_golang/prometheus versions for encoding-type skew and align them.","Inspect the panic stack trace to find which caller passed an unexpected chunk encoding; fix it to pass a plain (sub-)chunk.","If a new upstream chunk encoding exists, extend the switch with the corresponding storepb.Chunk type.","Report as a bug with the block/query details if it occurs on stock code paths — panics here indicate an internal invariant break."],"exampleFix":"// before\nfunc chunkToStoreEncoding(e chunkenc.Encoding) storepb.Chunk_Encoding {\n    switch e {\n    case chunkenc.EncXOR:\n        return storepb.Chunk_XOR\n    ...\n    default:\n        panic(\"unknown chunk encoding\")\n    }\n}\n// after\ndefault:\n    return storepb.Chunk_UNKNOWN // or return an error instead of panicking","handlingStrategy":"type-guard","validationCode":"func isPlainChunkEncoding(e chunkenc.Encoding) bool {\n    switch e {\n    case chunkenc.EncXOR, chunkenc.EncHistogram, chunkenc.EncFloatHistogram:\n        return true\n    }\n    return false\n}","typeGuard":"func canMapToStoreEncoding(e chunkenc.Encoding) bool {\n    return e == chunkenc.EncXOR || e == chunkenc.EncHistogram || e == chunkenc.EncFloatHistogram\n}","tryCatchPattern":"// panic is not recoverable via error; guard the call site\nif !canMapToStoreEncoding(ch.Encoding()) {\n    return status.Errorf(codes.Internal, \"unexpected chunk encoding %d\", ch.Encoding())\n}\ntype := chunkToStoreEncoding(ch.Encoding())","preventionTips":["Never pass AggrChunk containers into chunkToStoreEncoding; only pass sub-chunks.","Extend the encoding switch whenever new upstream chunk encodings are adopted.","Add a unit test covering every chunkenc.Encoding constant against the mapper."],"tags":["thanos","panic","chunk-encoding","invariant"],"backgroundTag":"internal-invariant-violation","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"}