apache/druid · error · ExpressionValidationException

needs a number as its first argument but got %s instead

Error message

needs a number as its first argument but got %s instead

What it means

Thrown by Druid's HUMAN_READABLE_BYTES_FORMAT expression function when the first argument (the byte count to format) is neither LONG nor DOUBLE at validation time. Only numeric values are accepted; a DOUBLE is cast to LONG before formatting.

Source

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

  abstract class SizeFormatFunc implements Function
  {
    protected abstract HumanReadableBytes.UnitSystem getUnitSystem();

    @Override
    public ExprEval apply(List<Expr> args, Expr.ObjectBinding bindings)
    {
      final ExprEval valueParam = args.get(0).eval(bindings);
      if (valueParam.isNumericNull()) {
        return ExprEval.ofString(null);
      }

      /**
       * only LONG and DOUBLE are allowed
       * For a DOUBLE, it will be cast to LONG before format
       */
      if (valueParam.value() != null && !valueParam.type().anyOf(ExprType.LONG, ExprType.DOUBLE)) {
        throw validationFailed(
            "needs a number as its first argument but got %s instead",
            valueParam.type()
        );
      }

      /**
       * By default, precision is 2
       */
      long precision = 2;
      if (args.size() > 1) {
        ExprEval precisionParam = args.get(1).eval(bindings);
        if (precisionParam.value() == null) {
          throw validationFailed("needs a LONG as its second argument but got null");
        }
        if (!precisionParam.type().is(ExprType.LONG)) {
          throw validationFailed("needs a LONG as its second argument but got %s instead", precisionParam.type());
        }
        precision = precisionParam.asLong();

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Cast the first argument: CAST(size_bytes AS BIGINT) before calling the function.
  2. Use a numeric literal instead of a quoted one, e.g. human_readable_bytes_format(1024).
  3. Fix ingestion/rollup typing so the column is stored as LONG.
  4. Validate the expression type in a dry-run/EXPLAIN PLAN before running the query.

Example fix

// before
human_readable_bytes_format(byte_str)
// after
human_readable_bytes_format(CAST(byte_str AS BIGINT))
Defensive patterns

Strategy: validation

Validate before calling

CAST(size_expr AS BIGINT) -- apply before human_readable_bytes_format

Type guard

// only allow numeric args
if (!(v instanceof Number)) throw new IllegalArgumentException("byte count must be numeric");

Prevention

When it happens

Trigger: Calling human_readable_bytes_format with a STRING, BOOLEAN, or other non-numeric first argument, e.g. human_readable_bytes_format('1024') where the string was never cast.

Common situations: Ingested size fields stored as strings (CSV/JSON inputs); users forgetting CAST(col AS BIGINT); binding parameters typed as strings from client frameworks.

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