apache/druid · error · ExpressionValidationException

first argument should be a LONG or DOUBLE but got

Error message

first argument should be a LONG or DOUBLE but got %s instead

What it means

This two-argument math expression function requires its first argument to be numeric (LONG or DOUBLE). If args[0] evaluates to any other expression type (STRING, complex, array), validation fails with this message naming the actual type. Null is accepted (returns NULL).

Solutions

  1. Wrap the first argument in CAST(... AS BIGINT) or CAST(... AS DOUBLE)
  2. Verify the operand column's type with EXPLAIN PLAN and correct the column reference
  3. Fix the ingestion/rollup spec so the source column is numeric
  4. Handle string inputs explicitly; only nulls are tolerated without a cast

Example fix

// before: FUNC(stringCol, 2) -> throws
// after: FUNC(CAST(stringCol AS DOUBLE), 2)
Defensive patterns

Strategy: validation

Validate before calling

ExpressionType t = args.get(0).eval(bindings).type();
if (!(t.anyOf(ExprType.LONG, ExprType.DOUBLE))) {
  throw new IllegalArgumentException("first arg must be LONG/DOUBLE, got " + t);
}

Type guard

static boolean isFirstArgNumeric(ExprEval<?> e) {
  return e.type().anyOf(ExprType.LONG, ExprType.DOUBLE);
}

Prevention

When it happens

Trigger: Evaluating the function where args[0] resolves to a non-numeric type, e.g. a string dimension or nested-data column.

Common situations: Using the function on a VARCHAR column without a cast; ingestion-spec expressions referencing the wrong input column; schema changes turning a numeric column into string.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/math/expr/Function.java:1513

    public static final String NAME = "round";

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

    @Override
    public ExprEval apply(List<Expr> args, Expr.ObjectBinding bindings)
    {
      ExprEval value1 = args.get(0).eval(bindings);

      if (value1.isNumericNull()) {
        return ExprEval.ofLong(null);
      }

      if (!value1.type().anyOf(ExprType.LONG, ExprType.DOUBLE)) {
        throw validationFailed(
            "first argument should be a LONG or DOUBLE but got %s instead",
            value1.type()
        );
      }

      if (args.size() == 1) {
        return eval(value1);
      } else {
        ExprEval value2 = args.get(1).eval(bindings);
        if (!value2.type().is(ExprType.LONG)) {
          throw validationFailed(
              "second argument should be a LONG but got %s instead",
              value2.type()
          );
        }
        return eval(value1, value2.asInt());
      }
    }

View on GitHub (pinned to 9b90983fd2)