apache/druid · error · IllegalArgumentException

Unknown operation[%s], known operations[%s]

Error message

Unknown operation[%s], known operations[%s]

What it means

ArithmeticPostAggregator's constructor resolves fnName through Ops.lookup and throws IllegalArgumentException when the operation name is not one of the known arithmetic ops (+, -, *, /, quotient). This fails fast at query/segment setup rather than producing wrong results.

Source

Thrown at processing/src/main/java/org/apache/druid/query/aggregation/post/ArithmeticPostAggregator.java:89

      @JsonProperty("fn") String fnName,
      @JsonProperty("fields") List<PostAggregator> fields,
      @JsonProperty("ordering") @Nullable String ordering
  )
  {
    Preconditions.checkArgument(fnName != null, "fn cannot not be null");
    Preconditions.checkArgument(
        fields != null && fields.size() > 1,
        "Illegal number of fields[%s], must be > 1",
        fields.size()
    );

    this.name = name;
    this.fnName = fnName;
    this.fields = fields;

    this.op = Ops.lookup(fnName);
    if (op == null) {
      throw new IAE("Unknown operation[%s], known operations[%s]", fnName, Ops.getFns());
    }

    this.ordering = ordering;
    this.comparator = ordering == null ? DEFAULT_COMPARATOR : Ordering.valueOf(ordering);
  }

  @Override
  public Set<String> getDependentFields()
  {
    Set<String> dependentFields = new HashSet<>();
    for (PostAggregator field : fields) {
      dependentFields.addAll(field.getDependentFields());
    }
    return dependentFields;
  }

  @Override
  public Comparator getComparator()

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Use one of the known operator strings exactly: +, -, *, /, or quotient
  2. Check Ops.getFns() (shown in the exception message) for the accepted set
  3. For division with double semantics prefer "/"; use "quotient" only for integer-style division behavior
  4. Validate operator names before deserializing user-supplied query JSON

Example fix

// before
new ArithmeticPostAggregator("ratio", "divide", fields, null);
// after
new ArithmeticPostAggregator("ratio", "/", fields, null);
Defensive patterns

Strategy: validation

Validate before calling

java.util.Set<String> known = Set.of("+","-","*","/","quotient");
if (fnName == null || !known.contains(fnName)) throw new IllegalArgumentException("bad op: " + fnName);

Type guard

boolean isValidArithOp(String fn) { return fn != null && Set.of("+","-","*","/","quotient").contains(fn); }

Try / catch

try { new ArithmeticPostAggregator(name, fnName, fields, ordering); } catch (IllegalArgumentException e) { /* fix fnName per message's known operations */ }

Prevention

When it happens

Trigger: Constructing ArithmeticPostAggregator with fnName set to an unrecognized string (e.g. "divide", "%", "plus", or a null/typo) in a JSON query spec or programmatic construction.

Common situations: Typos in hand-written native query JSON (e.g. "minus" vs "-"), migrating queries from SQL expressions to native post-aggregators, or generating specs dynamically with unvalidated operator input.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/d6d0aabe4d1ecf58. Report an issue: GitHub.