apache/druid · error · DruidException

index must be a numeric literal

Error message

index must be a numeric literal

What it means

REGEXP_EXTRACT accepts an optional third index argument that selects which capture group to return. It must be a numeric literal so the macro can resolve it at parse time; a non-literal or non-numeric value causes this validation failure.

Source

Thrown at processing/src/main/java/org/apache/druid/query/expression/RegexpExtractExprMacro.java:57

  {
    return FN_NAME;
  }

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

    final Expr arg = args.get(0);
    final Expr patternExpr = args.get(1);
    final Expr indexExpr = args.size() > 2 ? args.get(2) : null;

    if (!ExprUtils.isStringLiteral(patternExpr)) {
      throw validationFailed("pattern must be a string literal");
    }

    if (indexExpr != null && (!indexExpr.isLiteral() || !(indexExpr.getLiteralValue() instanceof Number))) {
      throw validationFailed("index must be a numeric literal");
    }

    // Precompile the pattern.
    final Pattern pattern = RegexpExprUtils.compilePattern((String) patternExpr.getLiteralValue(), FN_NAME);

    final int index = indexExpr == null ? 0 : ((Number) indexExpr.getLiteralValue()).intValue();

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

      @Nonnull
      @Override
      public ExprEval eval(final ObjectBinding bindings)
      {

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Use a plain numeric literal for the index, e.g. REGEXP_EXTRACT(x, '([a-z]+)', 1)
  2. Unquote the index if it was accidentally a string
  3. Omit the index entirely to use the default group 0

Example fix

// before
REGEXP_EXTRACT(col, '([a-z]+)', idx_col)
// after
REGEXP_EXTRACT(col, '([a-z]+)', 1)
Defensive patterns

Strategy: validation

Validate before calling

if (indexArg != null && !(indexArg instanceof Number)) {
  throw new IllegalArgumentException("index must be a numeric literal");
}

Type guard

static boolean isNumericLiteral(Expr e) {
  return e.isLiteral() && e.getLiteralValue() instanceof Number;
}

Try / catch

try {
  return macro.apply(args);
} catch (ExpressionValidationException e) {
  log.warn("Bad regexp_extract index arg: %s", e.getMessage());
  throw e;
}

Prevention

When it happens

Trigger: Calling REGEXP_EXTRACT(expr, 'pattern', idx) where idx is a column, an expression, a string like '1', or another non-numeric literal.

Common situations: Passing the group index from a query parameter/context instead of inlining it; quoting the index making it a string literal; using a float-typed column value.

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