thanos-io/thanos · error
put chunk
Error message
put chunk
What it means
w.chunkPool.Put failed while returning a written chunk to the chunk pool after it was added to the index. The pool rejects chunks whose concrete type/size doesn't match the pool's expectations, indicating an unexpected chunk type reached the writer.
Solutions
- Check the wrapped cause: it usually names the rejected chunk type; ensure source blocks use supported chunk encodings (XOR).
- Verify no error chunks (errChunk from failed populate) are passed onward — fail the compaction before Put when population failed.
- Align Thanos/Prometheus versions: blocks written by newer TSDB formats may carry unsupported encodings.
- If non-fatal in your flow, treat Put failures as a leak (skip) but log — though upstream expects a hard error.
Example fix
// before: error chunks reach the pool and fail Put
if err := w.chunkPool.Put(chk.Chunk); err != nil {
return errors.Wrap(err, "put chunk")
}
// after: skip pooling for non-XOR/err chunks
if ec, ok := chk.Chunk.(chunkenc.Chunk); ok && isSupportedPoolChunk(ec) {
if err := w.chunkPool.Put(ec); err != nil {
return errors.Wrap(err, "put chunk")
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// only pool chunks of a supported type
switch c := chk.Chunk.(type) {
case *chunkenc.XORChunk:
_ = pool.Put(c)
default:
// do not pool unknown/err chunks
} Type guard
func poolableChunk(c chunkenc.Chunk) bool {
if _, isErr := c.(errChunk); isErr { return false }
return c != nil && c.Encoding() == chunkenc.EncXOR
} Try / catch
if err := Put(chk.Chunk); err != nil {
level.Warn(logger).Log("msg", "chunk not poolable; leaking (non-fatal)", "err", err)
// do not abort compaction for a pool-miss
} Prevention
- Keep Thanos and Prometheus/TDengine TSDB versions aligned to avoid unknown chunk encodings
- Fail compaction on populate errors so errChunks never reach the pool
- Only pool chunks whose encoding matches the pool's registered types
- Add a guard test asserting pool input encodings in custom writer code
When it happens
Trigger: write() loops over written chunks and calls chunkPool.Put(chk.Chunk); failure when the chunk is not one of the pooled types (e.g. an errChunk or XOR chunk with unexpected encoding, or nil chunk), because the pool validates the chunk's class/size before recycling.
Common situations: A populate error turned the chunk into errChunk and it still flowed to Put, custom chunk encodings not supported by the pool, compaction of blocks with newer/unknown chunk format versions.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/c01cfee014403884.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/compactv2/chunk_series_set.go:228
}
// Skip the series with all deleted chunks.
if len(chks) == 0 {
// All series will be ignored.
p.SeriesProcessed()
continue
}
if err := sWriter.WriteChunks(chks...); err != nil {
return errors.Wrap(err, "write chunks")
}
if err := sWriter.AddSeries(ref, s.Labels(), chks...); err != nil {
return errors.Wrap(err, "add series")
}
for _, chk := range chks {
// ChunkPool is used by tsdb.OpenBlock BlockReader.
if err := w.chunkPool.Put(chk.Chunk); err != nil {
return errors.Wrap(err, "put chunk")
}
}
ref++
p.SeriesProcessed()
}
if populatedSet.Err() != nil {
return errors.Wrap(populatedSet.Err(), "iterate populated chunk series set")
}
return nil
}
View on GitHub (pinned to 35b8b99117)