apache/druid · error · DruidException

rank must be a number

Error message

rank must be a number

What it means

The ARRAY_QUANTILE expression macro requires its second argument ('rank') to be a literal number. Druid throws this ExprMacroTable validation error during expression compilation when the rank argument is a literal of a non-numeric type (e.g. a string), so the quantile function can never be evaluated.

Source

Thrown at processing/src/main/java/org/apache/druid/query/expression/ArrayQuantileExprMacro.java:67

  private static final String RANK_ARG_NAME = "rank";

  @Override
  public String name()
  {
    return FN_NAME;
  }

  @Override
  public Expr apply(final List<Expr> args)
  {
    validationHelperCheckArgumentCount(args, 2);

    final Expr arg = args.get(0);
    final Expr rankArg = args.get(1);

    validationHelperCheckArgIsLiteral(rankArg, RANK_ARG_NAME);
    if (!(rankArg.getLiteralValue() instanceof Number)) {
      throw validationFailed("%s must be a number", RANK_ARG_NAME);
    }

    final double rank = ((Number) rankArg.getLiteralValue()).doubleValue();

    class ArrayQuantileExpr extends ExprMacroTable.BaseScalarMacroFunctionExpr
    {
      private ArrayQuantileExpr(List<Expr> args)
      {
        super(ArrayQuantileExprMacro.this, args);
      }

      @Nonnull
      @Override
      public ExprEval<?> eval(final ObjectBinding bindings)
      {
        final DoubleList doubles = toDoubleArray(arg.eval(bindings));

        if (doubles == null) {

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Remove quotes from the rank argument so it is a numeric literal: ARRAY_QUANTILE(expr, 0.5).
  2. Ensure the rank argument is a literal constant, not a column or nested expression.
  3. Cast/convert the value to a number in the calling code before building the expression.

Example fix

-- before
SELECT ARRAY_QUANTILE(arr, '0.5') FROM t
-- after
SELECT ARRAY_QUANTILE(arr, 0.5) FROM t
Defensive patterns

Strategy: validation

Validate before calling

// JS/TS before emitting SQL
if (typeof rank !== 'number' || Number.isNaN(rank)) throw new Error('ARRAY_QUANTILE rank must be a numeric literal');

Type guard

function isNumericLiteral(x) { return typeof x === 'number' && Number.isFinite(x); }

Try / catch

try {
  return runDruidQuery(query);
} catch (ExpressionValidationException e) {
  if (e.getMessage().contains("rank must be a number")) {
    throw new UserInputException("Quantile rank must be an unquoted number, e.g. 0.5");
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling ARRAY_QUANTILE(expr, '0.5') in a Druid SQL/expression selector where the rank is quoted as a string; passing a non-literal (column reference) as rank; passing a literal boolean or null as the second argument.

Common situations: Hand-written SQL with quoted percentile values ('0.9'); generated SQL from BI tools that quotes all function arguments; users expecting the rank to be a column instead of a constant.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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