{"record":{"id":"9dfe4cc1d8008471","repo":"apache/druid","slug":"unknown-sketch-operation","errorCode":null,"errorMessage":"Unknown sketch operation ","messagePattern":"Unknown sketch operation ","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/theta/SketchHolder.java","lineNumber":311,"sourceCode":"        }\n        return SketchHolder.of(intersection.getResult(false, null));\n      case NOT:\n        if (holders.length < 1) {\n          throw new IllegalArgumentException(\"A-Not-B requires at least 1 sketch\");\n        }\n\n        if (holders.length == 1) {\n          return (SketchHolder) holders[0];\n        }\n\n        Sketch result = ((SketchHolder) holders[0]).getSketch();\n        for (int i = 1; i < holders.length; i++) {\n          AnotB anotb = (AnotB) SetOperation.builder().setNominalEntries(sketchSize).build(Family.A_NOT_B);\n          result = anotb.aNotB(result, ((SketchHolder) holders[i]).getSketch());\n        }\n        return SketchHolder.of(result);\n      default:\n        throw new IllegalArgumentException(\"Unknown sketch operation \" + func);\n    }\n  }\n\n  /**\n   *  Ideally make use of Sketch's equals and hashCode methods but which are not value based implementations.\n   *  And yet need value based equals and hashCode implementations for SketchHolder. \n   *  Hence using Arrays.equals() and Arrays.hashCode().\n   */\n  @Override\n  public boolean equals(Object o)\n  {\n    if (this == o) {\n      return true;\n    }\n    if (o == null || getClass() != o.getClass()) {\n      return false;\n    }\n    return Arrays.equals(this.getSketch().toByteArray(), ((SketchHolder) o).getSketch().toByteArray());","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/theta/SketchHolder.java#L293-L329","documentation":"sketchSetOperation() switches over the Func enum (UNION, INTERSECT, NOT). The default branch throws for any value it does not recognize, which can only occur if a Func constant was added by a newer datasketches extension than the code executing, or a null/unexpected func was coerced into the switch.","triggerScenarios":"Calling SketchHolder.sketchSetOperation(func, size, holders) where func is a Func value not handled by this switch — most commonly when Func was parsed from an unknown user-supplied string via Func.valueOf elsewhere, adding a new enum constant without updating this switch.","commonSituations":"Query JSON containing an unrecognized 'func' for a SketchSetPostAggregator; a version skew where a newer Druid serialized query references a Func the running nodes don't implement; typos like 'NOT_B' instead of 'NOT' caught earlier by valueOf but mapping to an unhandled constant.","solutions":["Use only supported func values: UNION, INTERSECT, NOT in query JSON","Upgrade the Druid cluster uniformly so all nodes recognize the same set of Func values","Check for recently added Func constants and update the switch in sketchSetOperation to handle them"],"exampleFix":"// before\nString func = \"A_NOT_B\"; // invalid in query JSON\n// after\nString func = \"NOT\"; // supported: UNION, INTERSECT, NOT","handlingStrategy":"validation","validationCode":"Set<String> allowed = Set.of(\"UNION\", \"INTERSECT\", \"NOT\");\nif (funcStr == null || !allowed.contains(funcStr)) {\n  throw new IllegalArgumentException(\"Unsupported sketch set op: \" + funcStr);\n}","typeGuard":"boolean isSupportedFunc(String s) {\n  return \"UNION\".equals(s) || \"INTERSECT\".equals(s) || \"NOT\".equals(s);\n}","tryCatchPattern":"try {\n  SketchHolder r = SketchHolder.sketchSetOperation(Func.valueOf(funcStr), size, holders);\n} catch (IllegalArgumentException e) {\n  // bad func name; surface a query-validation error to the user\n}","preventionTips":["Only emit UNION, INTERSECT, or NOT as func values in query JSON","Upgrade all Druid nodes together to avoid enum skew","Validate func strings at query-parse time"],"tags":["java","datasketches","invalid-enum"],"backgroundTag":"invalid-enum-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}