thanos-io/thanos · critical

unknown chunk encoding

Error message

unknown chunk encoding

What it means

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.

Solutions

  1. Check the Thanos and Prometheus client_golang/prometheus versions for encoding-type skew and align them.
  2. Inspect the panic stack trace to find which caller passed an unexpected chunk encoding; fix it to pass a plain (sub-)chunk.
  3. If a new upstream chunk encoding exists, extend the switch with the corresponding storepb.Chunk type.
  4. Report as a bug with the block/query details if it occurs on stock code paths — panics here indicate an internal invariant break.

Example fix

// before
func chunkToStoreEncoding(e chunkenc.Encoding) storepb.Chunk_Encoding {
    switch e {
    case chunkenc.EncXOR:
        return storepb.Chunk_XOR
    ...
    default:
        panic("unknown chunk encoding")
    }
}
// after
default:
    return storepb.Chunk_UNKNOWN // or return an error instead of panicking
Defensive patterns

Strategy: type-guard

Validate before calling

func isPlainChunkEncoding(e chunkenc.Encoding) bool {
    switch e {
    case chunkenc.EncXOR, chunkenc.EncHistogram, chunkenc.EncFloatHistogram:
        return true
    }
    return false
}

Type guard

func canMapToStoreEncoding(e chunkenc.Encoding) bool {
    return e == chunkenc.EncXOR || e == chunkenc.EncHistogram || e == chunkenc.EncFloatHistogram
}

Try / catch

// panic is not recoverable via error; guard the call site
if !canMapToStoreEncoding(ch.Encoding()) {
    return status.Errorf(codes.Internal, "unexpected chunk encoding %d", ch.Encoding())
}
type := chunkToStoreEncoding(ch.Encoding())

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at pkg/store/bucket.go:1499

			if err != nil {
				return err
			}
			out.Counter = &storepb.Chunk{Type: chunkToStoreEncoding(x.Encoding()), Data: b, Hash: hashChunk(hasher, b, calculateChecksum)}
		}
	}
	return nil
}

func chunkToStoreEncoding(in chunkenc.Encoding) storepb.Chunk_Encoding {
	switch in {
	case chunkenc.EncXOR:
		return storepb.Chunk_XOR
	case chunkenc.EncHistogram:
		return storepb.Chunk_HISTOGRAM
	case chunkenc.EncFloatHistogram:
		return storepb.Chunk_FLOAT_HISTOGRAM
	default:
		panic("unknown chunk encoding")
	}
}

func hashChunk(hasher hash.Hash64, b []byte, doHash bool) uint64 {
	if !doHash {
		return 0
	}
	hasher.Reset()
	// Write never returns an error on the hasher implementation
	_, _ = hasher.Write(b)
	return hasher.Sum64()
}

// debugFoundBlockSetOverview logs on debug level what exactly blocks we used for query in terms of
// labels and resolution. This is important because we allow mixed resolution results, so it is quite crucial
// to be aware what exactly resolution we see on query.
// TODO(bplotka): Consider adding resolution label to all results to propagate that info to UI and Query API.
func debugFoundBlockSetOverview(logger log.Logger, mint, maxt, maxResolutionMillis int64, lset labels.Labels, bs []*bucketBlock) {

View on GitHub (pinned to 35b8b99117)