{"record":{"id":"8f504d2a58b672cd","repo":"apache/druid","slug":"index-must-be-a-numeric-literal","errorCode":null,"errorMessage":"index must be a numeric literal","messagePattern":"index must be a numeric literal","errorType":"validation","errorClass":"DruidException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/expression/RegexpExtractExprMacro.java","lineNumber":57,"sourceCode":"  {\n    return FN_NAME;\n  }\n\n  @Override\n  public Expr apply(final List<Expr> args)\n  {\n    validationHelperCheckAnyOfArgumentCount(args, 2, 3);\n\n    final Expr arg = args.get(0);\n    final Expr patternExpr = args.get(1);\n    final Expr indexExpr = args.size() > 2 ? args.get(2) : null;\n\n    if (!ExprUtils.isStringLiteral(patternExpr)) {\n      throw validationFailed(\"pattern must be a string literal\");\n    }\n\n    if (indexExpr != null && (!indexExpr.isLiteral() || !(indexExpr.getLiteralValue() instanceof Number))) {\n      throw validationFailed(\"index must be a numeric literal\");\n    }\n\n    // Precompile the pattern.\n    final Pattern pattern = RegexpExprUtils.compilePattern((String) patternExpr.getLiteralValue(), FN_NAME);\n\n    final int index = indexExpr == null ? 0 : ((Number) indexExpr.getLiteralValue()).intValue();\n\n    class RegexpExtractExpr extends ExprMacroTable.BaseScalarMacroFunctionExpr\n    {\n      private RegexpExtractExpr(List<Expr> args)\n      {\n        super(RegexpExtractExprMacro.this, args);\n      }\n\n      @Nonnull\n      @Override\n      public ExprEval eval(final ObjectBinding bindings)\n      {","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/expression/RegexpExtractExprMacro.java#L39-L75","documentation":"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.","triggerScenarios":"Calling REGEXP_EXTRACT(expr, 'pattern', idx) where idx is a column, an expression, a string like '1', or another non-numeric literal.","commonSituations":"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.","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"],"exampleFix":"// before\nREGEXP_EXTRACT(col, '([a-z]+)', idx_col)\n// after\nREGEXP_EXTRACT(col, '([a-z]+)', 1)","handlingStrategy":"validation","validationCode":"if (indexArg != null && !(indexArg instanceof Number)) {\n  throw new IllegalArgumentException(\"index must be a numeric literal\");\n}","typeGuard":"static boolean isNumericLiteral(Expr e) {\n  return e.isLiteral() && e.getLiteralValue() instanceof Number;\n}","tryCatchPattern":"try {\n  return macro.apply(args);\n} catch (ExpressionValidationException e) {\n  log.warn(\"Bad regexp_extract index arg: %s\", e.getMessage());\n  throw e;\n}","preventionTips":["Pass capture-group index as unquoted integers","Omit the index when group 0 suffices","Lint generated expression JSON for literal types"],"tags":["druid","regex","literal"],"backgroundTag":"invalid-argument-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}