{"record":{"id":"81d97b1b7bef8a6d","repo":"apache/druid","slug":"number-of-metriccolumns-d-must-agree-with-numva","errorCode":null,"errorMessage":"Number of metricColumns [%d] must agree with numValues [%d]","messagePattern":"Number of metricColumns \\[(.+?)\\] must agree with numValues \\[(.+?)\\]","errorType":"validation","errorClass":"org.apache.druid.java.util.common.IAE","httpStatus":null,"severity":"error","filePath":"extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/tuple/ArrayOfDoublesSketchAggregatorFactory.java","lineNumber":83,"sourceCode":"  @Nullable private final List<String> metricColumns; \n\n  @JsonCreator\n  public ArrayOfDoublesSketchAggregatorFactory(\n      @JsonProperty(\"name\") final String name,\n      @JsonProperty(\"fieldName\") final String fieldName,\n      @JsonProperty(\"nominalEntries\") @Nullable final Integer nominalEntries,\n      @JsonProperty(\"metricColumns\") @Nullable final List<String> metricColumns,\n      @JsonProperty(\"numberOfValues\") @Nullable final Integer numberOfValues\n  )\n  {\n    this.name = Preconditions.checkNotNull(name, \"Must have a valid, non-null aggregator name\");\n    this.fieldName = Preconditions.checkNotNull(fieldName, \"Must have a valid, non-null fieldName\");\n    this.nominalEntries = nominalEntries == null ? ThetaUtil.DEFAULT_NOMINAL_ENTRIES : nominalEntries;\n    Util.checkIfIntPowerOf2(this.nominalEntries, \"nominalEntries\");\n    this.metricColumns = metricColumns;\n    this.numberOfValues = numberOfValues == null ? (metricColumns == null ? 1 : metricColumns.size()) : numberOfValues;\n    if (metricColumns != null && metricColumns.size() != this.numberOfValues) {\n      throw new IAE(\n          \"Number of metricColumns [%d] must agree with numValues [%d]\",\n          metricColumns.size(),\n          this.numberOfValues\n      );\n    }\n  }\n\n  @Override\n  public Aggregator factorize(final ColumnSelectorFactory metricFactory)\n  {\n    if (metricColumns == null) { // input is sketches, use merge aggregator\n      final BaseObjectColumnValueSelector<ArrayOfDoublesSketch> selector = metricFactory\n          .makeColumnValueSelector(fieldName);\n      if (selector instanceof NilColumnValueSelector) {\n        return new NoopArrayOfDoublesSketchAggregator(numberOfValues);\n      }\n      return new ArrayOfDoublesSketchMergeAggregator(selector, nominalEntries, numberOfValues);\n    }","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/tuple/ArrayOfDoublesSketchAggregatorFactory.java#L65-L101","documentation":"ArrayOfDoublesSketchAggregatorFactory maintains metricColumns (the per-row double columns aggregated) and numberOfValues (how many doubles each sketch row holds). If metricColumns is provided but its size differs from numberOfValues (explicitly set or defaulted), the constructor throws an IAE because the sketch structure would be inconsistent.","triggerScenarios":"Constructing new ArrayOfDoublesSketchAggregatorFactory(name, fieldName, nominalEntries, metricColumns, numberOfValues) where metricColumns != null and numberOfValues (explicit or defaulted to metricColumns.size()) conflicts — e.g. metricColumns=[a,b,c] with numberOfValues=2.","commonSituations":"Hand-written query JSON where 'numValues' doesn't match the length of 'metricColumns'; a stored spec edited to add a metric column without updating numValues; programmatic factory construction passing a stale numberOfValues.","solutions":["Set numberOfValues to metricColumns.size(), or omit numberOfValues so it defaults from metricColumns","Fix the query/ingestion spec JSON so numValues equals the number of entries in metricColumns","If metricColumns is irrelevant, pass null for it and specify numberOfValues directly"],"exampleFix":"// before\nnew ArrayOfDoublesSketchAggregatorFactory(\"agg\", \"sketch\", 16384,\n    Arrays.asList(\"m1\", \"m2\", \"m3\"), 2); // mismatch\n// after\nnew ArrayOfDoublesSketchAggregatorFactory(\"agg\", \"sketch\", 16384,\n    Arrays.asList(\"m1\", \"m2\", \"m3\"), 3); // or pass null for numberOfValues","handlingStrategy":"validation","validationCode":"if (metricColumns != null && numberOfValues != null\n    && metricColumns.size() != numberOfValues) {\n  throw new IllegalArgumentException(\n      \"metricColumns size \" + metricColumns.size() + \" != numValues \" + numberOfValues);\n}","typeGuard":"boolean isConsistent(List<String> metricColumns, Integer numberOfValues) {\n  return metricColumns == null || numberOfValues == null\n      || metricColumns.size() == numberOfValues;\n}","tryCatchPattern":"try {\n  ArrayOfDoublesSketchAggregatorFactory f = new ArrayOfDoublesSketchAggregatorFactory(\n      name, fieldName, nominalEntries, metricColumns, numberOfValues);\n} catch (IllegalArgumentException e) {\n  // fix spec: align numValues with metricColumns size or omit numValues\n}","preventionTips":["Omit numberOfValues and let it default from metricColumns.size()","When editing ingestion specs, update numValues and metricColumns together","Validate spec JSON before submission with a schema check"],"tags":["java","datasketches","tuple-sketch"],"backgroundTag":"invalid-argument-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"}