apache/druid · error · IllegalStateException
Unknown version[ ] of MetricHolder
Error message
Unknown version[%s] of MetricHolder
What it means
MetricHolder.fromByteBuffer reads a legacy (v8) segment metric column and throws ISE if the version byte is not the expected VERSION[0]. This protects against reading metric columns in an on-disk format the loader cannot parse.
Solutions
- Verify segment integrity (re-download/re-pull the segment from deep storage)
- Re-ingest the affected segments so they are written in the current format
- Upgrade Druid if the segments were written by a newer format than the reader supports
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
// check segment descriptor/version metadata before loading legacy metric columns
if (!segmentVersion.equals("v8-compatible")) { re-ingest; } Try / catch
try { MetricHolder.fromByteBuffer(buf); } catch (ISE e) { if (e.getMessage().contains("Unknown version")) { /* quarantine/re-download segment */ } else throw e; } Prevention
- Keep all Druid nodes on the same version
- Validate segment checksums after copying between clusters
- Re-ingest segments written by very old formats
When it happens
Trigger: Reading a metric column whose stored version byte differs from the expected one — corrupted segment files, hand-modified segments, or segments written by incompatible Druid versions.
Common situations: Mounting segments copied from a different Druid version or disk-format era; truncated/corrupted segment files on deep storage or local cache.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/92f3a62a57aadc44.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/segment/MetricHolder.java:48
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
*/
public class MetricHolder
{
private static final byte[] VERSION = new byte[]{0x0};
private static final SerializerUtils SERIALIZER_UTILS = new SerializerUtils();
/**
* Read a metric column from a legacy (v8) segment.
*/
public static MetricHolder fromByteBuffer(ByteBuffer buf)
{
final byte ver = buf.get();
if (VERSION[0] != ver) {
throw new ISE("Unknown version[%s] of MetricHolder", ver);
}
final String metricName = SERIALIZER_UTILS.readString(buf);
final String typeName = SERIALIZER_UTILS.readString(buf);
MetricHolder holder = new MetricHolder(metricName, typeName);
switch (holder.type) {
case FLOAT:
holder.floatType = CompressedColumnarFloatsSupplier.fromByteBuffer(
buf,
ByteOrder.nativeOrder(),
null // OK since this method is only used for legacy segments, which always use version 1 indexed
);
break;
case COMPLEX:
final ComplexMetricSerde serdeForType = ComplexMetrics.getSerdeForType(holder.getTypeName());
if (serdeForType == null) {View on GitHub (pinned to 9b90983fd2)