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
- Use a plain numeric literal for the index, e.g. REGEXP_EXTRACT(x, '([a-z]+)', 1)
- Unquote the index if it was accidentally a string
- 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
- Pass capture-group index as unquoted integers
- Omit the index when group 0 suffices
- Lint generated expression JSON for literal types
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
- pattern must be a string literal
- pattern must be a STRING literal
- pattern must be a string literal
- replacement must be a string literal
- Incorrect Regex: %s . No match found.
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/8f504d2a58b672cd.
Report an issue: GitHub.