apache/druid · error · ExpressionValidationException

second argument should be a LONG but got

Error message

second argument should be a LONG but got %s instead

What it means

The same function family requires the second (optional) argument to be a LONG. If args[1] evaluates to STRING, DOUBLE, or another non-LONG type, the function throws this validation error instead of coercing.

Solutions

  1. Change the second argument to an integer literal: FUNC(x, 2) not FUNC(x, 2.0)
  2. Cast explicitly: CAST(col AS BIGINT) when the operand is DOUBLE or STRING
  3. Remove surrounding quotes so the argument is not parsed as a string
  4. Check EXPLAIN PLAN for the second operand's inferred type

Example fix

// before: FUNC(x, 2.5) -> throws
// after: FUNC(x, CAST(2.5 AS BIGINT)) or FUNC(x, 2)
Defensive patterns

Strategy: validation

Validate before calling

ExprEval<?> v2 = args.get(1).eval(bindings);
if (!v2.type().is(ExprType.LONG)) {
  throw new IllegalArgumentException("second arg must be LONG, got " + v2.type());
}

Type guard

static boolean isSecondArgLong(ExprEval<?> e) {
  return e.type().is(ExprType.LONG);
}

Prevention

When it happens

Trigger: Passing a double literal or string as the second argument, e.g. FUNC(x, 2.0) or FUNC(x, '2'); passing a double-typed column as the second operand.

Common situations: Numeric literals written as 2.0 instead of 2; columns inferred as DOUBLE; quoting numbers in expression strings making them strings.

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/ea87ddc63ed99346. Report an issue: GitHub.

Appendix: source

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

      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());
      }
    }

    @Override
    public void validateArguments(List<Expr> args)
    {
      validationHelperCheckAnyOfArgumentCount(args, 1, 2);
    }

    @Nullable
    @Override
    public ExpressionType getOutputType(Expr.InputBindingInspector inspector, List<Expr> args)
    {

View on GitHub (pinned to 9b90983fd2)