{"record":{"id":"1bebff5af18db781","repo":"apache/druid","slug":"pattern-must-be-a-string-literal-1bebff","errorCode":null,"errorMessage":"pattern must be a STRING literal","messagePattern":"pattern must be a STRING literal","errorType":"validation","errorClass":"DruidException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/expression/RegexpLikeExprMacro.java","lineNumber":84,"sourceCode":"      return ExpressionType.LONG;\n    }\n  }\n\n  /**\n   * Expr when pattern is a literal.\n   */\n  class RegexpLikeExpr extends BaseRegexpLikeExpr\n  {\n    private final Expr arg;\n    private final Pattern pattern;\n\n    private RegexpLikeExpr(List<Expr> args)\n    {\n      super(args);\n\n      final Expr patternExpr = args.get(1);\n      if (!ExprUtils.isStringLiteral(patternExpr)) {\n        throw validationFailed(\"pattern must be a STRING literal\");\n      }\n\n      final String patternString = (String) patternExpr.getLiteralValue();\n      this.arg = args.get(0);\n      this.pattern = RegexpExprUtils.compilePattern(patternString, FN_NAME);\n    }\n\n    @Nonnull\n    @Override\n    public ExprEval<?> eval(final ObjectBinding bindings)\n    {\n      final String s = arg.eval(bindings).asString();\n      if (s == null) {\n        return ExprEval.ofLong(null);\n      } else {\n        final Matcher matcher = pattern.matcher(s);\n        return ExprEval.ofLongBoolean(matcher.find());\n      }","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/expression/RegexpLikeExprMacro.java#L66-L102","documentation":"The regexp_like macro's RegexpLikeExpr constructor compiles the pattern eagerly at parse time and therefore requires the pattern (second argument) to be a string literal. Any non-literal or non-string value triggers this validation failure.","triggerScenarios":"REGEXP_LIKE(expr, pattern) where pattern is a column, a non-literal expression, or a literal of non-string type (number/boolean/null).","commonSituations":"Patterns read from data or config at runtime; numeric literal passed instead of string; generated native JSON where the pattern field is a JSON number.","solutions":["Supply the pattern as a quoted string literal","Cast or restructure so the regex is fixed at query-writing time","Use REGEXP operator alternatives in SQL that accept expressions if dynamic patterns are needed"],"exampleFix":"// before\nREGEXP_LIKE(col, 123)\n// after\nREGEXP_LIKE(col, '123')","handlingStrategy":"validation","validationCode":"if (!(patternExpr instanceof LiteralExpr) || !(((LiteralExpr) patternExpr).getValue() instanceof String)) {\n  throw new IllegalArgumentException(\"pattern must be a string literal\");\n}","typeGuard":"static boolean isStringLiteral(Expr e) {\n  return ExprUtils.isStringLiteral(e);\n}","tryCatchPattern":"try {\n  return expr.eval(bindings);\n} catch (ExpressionValidationException e) {\n  return ExprEval.ofLong(null);\n}","preventionTips":["Keep regex patterns static in the query text","Cast numeric-looking patterns to quoted strings","Test expressions with Parser.parse before production"],"tags":["druid","regex","literal"],"backgroundTag":"invalid-regex-pattern","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"}