{"record":{"id":"4d9fa2e44007f15f","repo":"apache/druid","slug":"object-is-not-of-a-type-that-can-be-deserialized-t-4d9fa2","errorCode":null,"errorMessage":"Object is not of a type that can be deserialized to a quantiles DoublesSketch: %s","messagePattern":"Object is not of a type that can be deserialized to a quantiles DoublesSketch: (.+?)","errorType":"exception","errorClass":"org.apache.druid.java.util.common.ISE","httpStatus":null,"severity":"error","filePath":"extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/quantiles/DoublesSketchOperations.java","lineNumber":44,"sourceCode":"import org.apache.druid.segment.data.SafeWritableMemory;\n\nimport java.nio.charset.StandardCharsets;\n\npublic class DoublesSketchOperations\n{\n\n  public static final DoublesSketch EMPTY_SKETCH = DoublesSketch.builder().build();\n\n  public static DoublesSketch deserialize(final Object serializedSketch)\n  {\n    if (serializedSketch instanceof String) {\n      return deserializeFromBase64EncodedString((String) serializedSketch);\n    } else if (serializedSketch instanceof byte[]) {\n      return deserializeFromByteArray((byte[]) serializedSketch);\n    } else if (serializedSketch instanceof DoublesSketch) {\n      return (DoublesSketch) serializedSketch;\n    }\n    throw new ISE(\n        \"Object is not of a type that can be deserialized to a quantiles DoublesSketch: %s\",\n        serializedSketch == null ? \"null\" : serializedSketch.getClass()\n    );\n  }\n\n  public static DoublesSketch deserializeSafe(final Object serializedSketch)\n  {\n    if (serializedSketch instanceof String) {\n      return deserializeFromBase64EncodedStringSafe((String) serializedSketch);\n    } else if (serializedSketch instanceof byte[]) {\n      return deserializeFromByteArraySafe((byte[]) serializedSketch);\n    }\n    return deserialize(serializedSketch);\n  }\n\n  public static DoublesSketch deserializeFromBase64EncodedString(final String str)\n  {\n    return deserializeFromByteArray(StringUtils.decodeBase64(str.getBytes(StandardCharsets.UTF_8)));","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/quantiles/DoublesSketchOperations.java#L26-L62","documentation":"DoublesSketchOperations.deserialize coerces an Object (typically from a query result or serialized field) into a quantiles DoublesSketch. It supports String (base64), byte[], and DoublesSketch instances; anything else — including null — is rejected with an IllegalStateException. This guards against feeding non-sketch data into sketch post-aggregators.","triggerScenarios":"Calling deserialize() (directly or via callers like deserializeSafe consumers) with an Object whose runtime type is not String, byte[], or DoublesSketch — e.g. a Map, List, Number, or null returned from a previous stage or stored field.","commonSituations":"Group-by results where the sketch column was coerced to a JSON map/array, ingestion storing the wrong metric type in the column, passing the output of a different post-aggregator (e.g. a double[] histogram) into a sketch post-agg.","solutions":["Inspect the actual value's class (the message prints it) and ensure the field being consumed is the raw sketch bytes/base64 string, not a decoded structure.","Fix the upstream aggregation/post-aggregator chain so the field computes a DoublesSketch (e.g. use quantilesDoublesSketch aggregation directly).","If the value is JSON-deserialized into a Map/List, re-serialize to base64 byte[] or store as raw bytes at ingestion time.","Handle null explicitly: verify the column actually contains sketch data for every row instead of relying on deserialize to cope with null."],"exampleFix":"// before\nObject val = results.get(\"sketch\"); // a List<Double> after JSON round-trip\nDoublesSketch s = DoublesSketchOperations.deserialize(val); // ISE\n// after\nDoublesSketch s = DoublesSketchOperations.deserialize(\n    base64Encode(reSerializeAsSketchBytes(val))); // pass String or byte[]","handlingStrategy":"type-guard","validationCode":"if (val == null || !(val instanceof String || val instanceof byte[] || val instanceof DoublesSketch)) { throw new IllegalArgumentException(\"field must be base64 String, byte[], or DoublesSketch, got: \" + (val == null ? \"null\" : val.getClass())); }","typeGuard":"static boolean isSketchLike(Object o) { return o instanceof DoublesSketch || o instanceof byte[] || o instanceof String; }","tryCatchPattern":"try { DoublesSketch s = DoublesSketchOperations.deserialize(val); } catch (IllegalStateException e) { log.error(\"Non-sketch value: {}\", e.getMessage()); }","preventionTips":["Keep sketch fields as raw bytes through ingestion and query results (avoid JSON round-trips that decode them).","Verify column metric type is the sketch aggregator, not a generic serializer.","Log/inspect obj.getClass() before deserializing dynamically-typed results."],"tags":["druid","datasketches","deserialization","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}