apache/druid · error · DruidException
pattern must be a string literal
Error message
pattern must be a string literal
What it means
regexp_replace's RegexpReplaceExpr constructor requires the pattern argument to be a string literal (or an explicit literal NULL, which is tolerated and disables matching). Any other pattern expression fails validation because patterns are precompiled at parse time.
Source
Thrown at processing/src/main/java/org/apache/druid/query/expression/RegexpReplaceExprMacro.java:88
/**
* Expr when pattern and replacement are literals.
*/
class RegexpReplaceExpr extends BaseRegexpReplaceExpr
{
private final Expr arg;
private final Pattern pattern;
private final String replacement;
private RegexpReplaceExpr(List<Expr> args)
{
super(args);
final Expr patternExpr = args.get(1);
final Expr replacementExpr = args.get(2);
if (!ExprUtils.isStringLiteral(patternExpr)
&& !(patternExpr.isLiteral() && patternExpr.getLiteralValue() == null)) {
throw validationFailed("pattern must be a string literal");
}
if (!ExprUtils.isStringLiteral(replacementExpr)
&& !(replacementExpr.isLiteral() && replacementExpr.getLiteralValue() == null)) {
throw validationFailed("replacement must be a string literal");
}
final String patternString = (String) patternExpr.getLiteralValue();
this.arg = args.get(0);
this.pattern = patternString != null ? RegexpExprUtils.compilePattern(patternString, FN_NAME) : null;
this.replacement = (String) replacementExpr.getLiteralValue();
}
@Nonnull
@Override
public ExprEval<?> eval(final ObjectBinding bindings)
{View on GitHub (pinned to 9b90983fd2)
Solutions
- Provide the pattern as a quoted string literal
- If a NULL pattern is intended, make it an explicit literal NULL (this is accepted)
- Restructure the query so pattern matching happens outside the expression
Example fix
// before REGEXP_REPLACE(col, pat_col, 'X') // after REGEXP_REPLACE(col, '[aeiou]', 'X')
Defensive patterns
Strategy: validation
Validate before calling
boolean ok = ExprUtils.isStringLiteral(patternExpr)
|| (patternExpr.isLiteral() && patternExpr.getLiteralValue() == null);
if (!ok) {
throw new IllegalArgumentException("pattern must be a string literal");
} Type guard
static boolean isStringOrNullLiteral(Expr e) {
return ExprUtils.isStringLiteral(e) || (e.isLiteral() && e.getLiteralValue() == null);
} Try / catch
try {
return macro.apply(args);
} catch (ExpressionValidationException e) {
log.error("regexp_replace pattern invalid: %s", e.getMessage());
throw e;
} Prevention
- Inline patterns as quoted strings
- Only use literal NULL when null-pattern semantics are intended
- Dry-run parse expressions before query execution
When it happens
Trigger: REGEXP_REPLACE(expr, pattern, replacement) where pattern is a column reference, computed expression, or non-string non-null literal.
Common situations: Dynamic regex patterns sourced from data; forgetting quotes so the pattern parses as an identifier; generated queries with concatenated pattern fields.
Related errors
- pattern must be a string literal
- index must be a numeric 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/3adcd3c5705ab9b0.
Report an issue: GitHub.