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

  1. Check the wrapped cause: it usually names the rejected chunk type; ensure source blocks use supported chunk encodings (XOR).
  2. Verify no error chunks (errChunk from failed populate) are passed onward — fail the compaction before Put when population failed.
  3. Align Thanos/Prometheus versions: blocks written by newer TSDB formats may carry unsupported encodings.
  4. 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

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)