{"record":{"id":"75af7c31d37a4851","repo":"apache/druid","slug":"can-t-get-sketch-from-object-of-type-s","errorCode":null,"errorMessage":"Can't get sketch from object of type [%s]","messagePattern":"Can't get sketch from object of type \\[(.+?)\\]","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/theta/SketchHolder.java","lineNumber":155,"sourceCode":"    } else {\n      union.union(getSketch());\n    }\n  }\n\n  public Sketch getSketch()\n  {\n    if (cachedSketch != null) {\n      return cachedSketch;\n    }\n\n    if (obj instanceof Sketch) {\n      cachedSketch = (Sketch) obj;\n    } else if (obj instanceof Union) {\n      cachedSketch = ((Union) obj).getResult();\n    } else if (obj instanceof Memory) {\n      cachedSketch = deserializeFromMemory((Memory) obj);\n    } else {\n      throw new ISE(\"Can't get sketch from object of type [%s]\", obj.getClass().getName());\n    }\n    return cachedSketch;\n  }\n\n  public double getEstimate()\n  {\n    if (cachedEstimate == null) {\n      cachedEstimate = getSketch().getEstimate();\n    }\n    return cachedEstimate.doubleValue();\n  }\n\n  public SketchEstimateWithErrorBounds getEstimateWithErrorBounds(int errorBoundsStdDev)\n  {\n    Sketch sketch = getSketch();\n    SketchEstimateWithErrorBounds result = new SketchEstimateWithErrorBounds(\n        getEstimate(),\n        sketch.getUpperBound(errorBoundsStdDev),","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/theta/SketchHolder.java#L137-L173","documentation":"SketchHolder.getSketch() converts the holder's underlying object into an Apache DataSketches Theta Sketch. It only knows how to handle Sketch, Union, and Memory instances; anything else reaches the final else branch and throws an ISE. This indicates the holder was constructed with (or a value deserialized into) an object of an unsupported type.","triggerScenarios":"Calling getSketch() (directly or via getEstimate(), equals(), hashCode(), or set operations) on a SketchHolder whose wrapped object is not a Sketch, Union, or Memory — e.g. after SketchHolder.of(someArbitraryObject) or deserializing a payload produced by an incompatible sketch version.","commonSituations":"Mixing DataSketches versions where serialized bytes yield an unexpected class; passing a nested SketchHolder instead of the raw sketch object; custom aggregation code stuffing a non-sketch object into SketchHolder.of(); classloader differences in federated/cluster deployments returning an unrecognized implementation.","solutions":["Check what object was passed to SketchHolder.of() and ensure it is a Sketch, Union, or Memory","Unwrap nested SketchHolder values with holder.getSketch() before passing them to of()","Align the datasketches-java dependency version across all Druid nodes so serialization round-trips produce known types","Log obj.getClass().getName() (it is already in the message) and add a type check before constructing the holder"],"exampleFix":"// before\nSketchHolder holder = SketchHolder.of(obj); // obj may be anything\nSketch sketch = holder.getSketch(); // may throw ISE\n// after\nif (obj instanceof SketchHolder) {\n  obj = ((SketchHolder) obj).getSketch();\n}\nif (!(obj instanceof Sketch) && !(obj instanceof Union) && !(obj instanceof Memory)) {\n  throw new IllegalArgumentException(\"Unsupported sketch object: \" + obj.getClass());\n}\nSketchHolder holder = SketchHolder.of(obj);","handlingStrategy":"type-guard","validationCode":"if (!(obj instanceof Sketch) && !(obj instanceof Union) && !(obj instanceof Memory)) {\n  throw new IllegalArgumentException(\"Unsupported sketch object: \" + obj.getClass().getName());\n}","typeGuard":"boolean isSketchable(Object o) {\n  return o instanceof Sketch || o instanceof Union || o instanceof Memory;\n}","tryCatchPattern":"try {\n  Sketch s = holder.getSketch();\n} catch (IllegalStateException e) {\n  // log obj class from message; fall back to re-wrapping via Memory.wrap(rawBytes)\n}","preventionTips":["Only pass Sketch, Union, or Memory instances to SketchHolder.of()","Unwrap nested SketchHolder values before wrapping","Pin the same datasketches-java version on all Druid nodes","Log obj.getClass().getName() near construction sites to catch bad types early"],"tags":["java","datasketches","type-mismatch"],"backgroundTag":"incompatible-source-type","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"}