{"record":{"id":"5e48b832859669b5","repo":"apache/druid","slug":"aggregator-s-cannot-vectorize","errorCode":null,"errorMessage":"Aggregator[%s] cannot vectorize","messagePattern":"Aggregator\\[(.+?)\\] cannot vectorize","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"warning","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/AggregatorFactory.java","lineNumber":71,"sourceCode":" * If it is a multi value column then each individual value should be taken into account for aggregation e.g. if a row\n * had value [\"1\",\"1\",\"1\"], doubleSum aggregation would take each of them and sum them to 3.\n */\n@ExtensionPoint\npublic abstract class AggregatorFactory implements Cacheable\n{\n  private static final Logger log = new Logger(AggregatorFactory.class);\n\n  public abstract Aggregator factorize(ColumnSelectorFactory metricFactory);\n\n  public abstract BufferAggregator factorizeBuffered(ColumnSelectorFactory metricFactory);\n\n  /**\n   * Create a VectorAggregator based on the provided column selector factory. Will throw an exception if\n   * this aggregation class does not support vectorization: check \"canVectorize\" first.\n   */\n  public VectorAggregator factorizeVector(VectorColumnSelectorFactory selectorFactory)\n  {\n    throw new UOE(\"Aggregator[%s] cannot vectorize\", getClass().getName());\n  }\n\n  /**\n   * Creates an {@link Aggregator} based on the provided column selector factory.\n   * The returned value is a holder object which contains both the aggregator\n   * and its initial size in bytes. The callers can then invoke\n   * {@link Aggregator#aggregateWithSize()} to perform aggregation and get back\n   * the incremental memory required in each aggregate call. Combined with the\n   * initial size, this gives the total on-heap memory required by the aggregator.\n   * <p>\n   * This method must include JVM object overheads in the estimated size and must\n   * ensure not to underestimate required memory as that might lead to OOM errors.\n   * <p>\n   * This flow does not require invoking {@link #guessAggregatorHeapFootprint(long)}\n   * which tends to over-estimate the required memory.\n   *\n   * @return AggregatorAndSize which contains the actual aggregator and its initial size.\n   */","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/AggregatorFactory.java#L53-L89","documentation":"AggregatorFactory.factorizeVector is a default method that subclasses must override to support the vectorized query engine; the base implementation always throws UOE. It should only be called when canVectorize() returns true, so hitting it means vectorization was attempted on an aggregator (or legacy storage path) that does not implement it.","triggerScenarios":"Running a query with vectorization enabled against a datasource/aggregator (custom aggregation, complex/aggregator combination) whose AggregatorFactory doesn't override factorizeVector or reports canVectorize incorrectly.","commonSituations":"Custom aggregator extensions that implement factorize but not factorizeVector; queries on segment storage lacking vectorization support while the engine assumes it; index.json/druid.query.vectorQuery default maxRows Intersecting a custom aggregator.","solutions":["Disable vectorization for this query: set the query context \"vectorize\": false (or tune druid.query.vectorQuery thresholds)","Implement factorizeVector (and canVectorize) in the custom AggregatorFactory","Upgrade the extension providing the aggregator to a version with vectorization support","Check canVectorize() before choosing the vectorized processing path"],"exampleFix":"// before\nqueryContext.put(\"vectorize\", true);\n// after\nif (!aggregatorFactory.canVectorize()) {\n  queryContext.put(\"vectorize\", false);\n} else {\n  queryContext.put(\"vectorize\", true);\n}","handlingStrategy":"try-catch","validationCode":"boolean safe = aggregatorFactories.stream().allMatch(AggregatorFactory::canVectorize);\nqueryContext.put(\"vectorize\", safe);\n","typeGuard":"boolean canVectorizeQuery(List<AggregatorFactory> aggs) {\n  return aggs.stream().allMatch(AggregatorFactory::canVectorize);\n}","tryCatchPattern":"try {\n  result = runVectorized(query);\n} catch (UnsupportedOperationException e) {\n  queryContext.put(\"vectorize\", false);\n  result = runQuery(query);\n}","preventionTips":["Call canVectorize() before factorizeVector","Implement factorizeVector in custom AggregatorFactory subclasses","Set \"vectorize\": false in query context for queries touching non-vectorizable aggregators"],"tags":["druid","aggregation","vectorization","unsupported-operation"],"backgroundTag":"method-not-implemented","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"}