apache/druid · error · ExpressionValidationException

Invalid type [%s]

Error message

Invalid type [%s]

What it means

The expression-language CAST(value, type) function parses its second argument as an ExpressionType via fromString (uppercased). If the string is not a registered type name (LONG, DOUBLE, FLOAT, STRING, ARRAY<...>, COMPLEX<...>), parsing throws IllegalArgumentException which is converted into this validation error.

Source

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

  }

  class CastFunc extends BivariateFunction
  {
    @Override
    public String name()
    {
      return "cast";
    }

    @Override
    protected ExprEval eval(ExprEval x, ExprEval y)
    {
      ExpressionType castTo;
      try {
        castTo = ExpressionType.fromString(StringUtils.toUpperCase(y.asString()));
      }
      catch (IllegalArgumentException e) {
        throw validationFailed("Invalid type [%s]", y.asString());
      }
      if (x.value() == null) {
        return ExprEval.ofType(castTo, null);
      } else {
        return x.castTo(castTo);
      }
    }

    @Override
    public Set<Expr> getScalarInputs(List<Expr> args)
    {
      if (args.get(1).isLiteral()) {
        ExpressionType castTo = ExpressionType.fromString(
            StringUtils.toUpperCase(args.get(1).getLiteralValue().toString())
        );
        switch (castTo.getType()) {
          case ARRAY:
            return Collections.emptySet();

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Use expression type names: 'LONG', 'DOUBLE', 'FLOAT', 'STRING', 'ARRAY<STRING>', etc.
  2. Replace SQL-only names: INT -> LONG, BIGINT -> LONG, VARCHAR -> STRING
  3. Validate the type string against ExpressionType.fromString before building the query dynamically
  4. Check the native query JSON expression, not the SQL text — the SQL layer rewrites casts automatically

Example fix

// before: CAST(x, 'INT') -> Invalid type [INT]
// after: CAST(x, 'LONG')
Defensive patterns

Strategy: validation

Validate before calling

Set<String> valid = Set.of("LONG","FLOAT","DOUBLE","STRING","ARRAY<STRING>","ARRAY<LONG>","ARRAY<DOUBLE>");
if (!valid.contains(typeStr.toUpperCase(Locale.ROOT))) {
  throw new IllegalArgumentException("unknown expression type " + typeStr);
}

Type guard

static boolean isValidExprTypeName(String s) {
  try { ExpressionType.fromString(StringUtils.toUpperCase(s)); return true; }
  catch (IllegalArgumentException e) { return false; }
}

Prevention

When it happens

Trigger: Calling CAST(x, 'INT') or CAST(x, 'VARCHAR') — SQL type names are not valid expression-language type names — or any misspelled type string inside a native expression.

Common situations: Writing SQL type names inside native-expression CAST(); typos like 'STRNG'; hand-rolled native queries generated from SQL dialect conventions (the SQL planner rewrites casts, raw expressions do not).

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