apache/druid · error · RE
Unrecognized unary operator %s
Error message
Unrecognized unary operator %s
What it means
During ANTLR-based expression parsing, ExprListenerImpl.exitUnaryOpExpr maps the parse-tree operator token to UnaryMinusExpr or UnaryNotExpr. Any other unary operator token reaches the default branch and throws a RuntimeException ('Unrecognized unary operator %s'), indicating the parser grammar and the listener are out of sync or the input produced an unexpected token.
Source
Thrown at processing/src/main/java/org/apache/druid/math/expr/ExprListenerImpl.java:83
Expr getAST()
{
return (Expr) nodes.get(rootNodeKey);
}
@Override
public void exitUnaryOpExpr(ExprParser.UnaryOpExprContext ctx)
{
int opCode = ((TerminalNode) ctx.getChild(0)).getSymbol().getType();
switch (opCode) {
case ExprParser.MINUS:
nodes.put(ctx, new UnaryMinusExpr(ctx.getChild(0).getText(), (Expr) nodes.get(ctx.getChild(1))));
break;
case ExprParser.NOT:
nodes.put(ctx, new UnaryNotExpr(ctx.getChild(0).getText(), (Expr) nodes.get(ctx.getChild(1))));
break;
default:
throw new RE("Unrecognized unary operator %s", ctx.getChild(0).getText());
}
}
@Override
public void exitApplyFunctionExpr(ExprParser.ApplyFunctionExprContext ctx)
{
String fnName = ctx.getChild(0).getText();
// Built-in functions.
final ApplyFunction function = Parser.getApplyFunction(fnName);
if (function == null) {
throw new RE("function '%s' is not defined.", fnName);
}
nodes.put(
ctx,
new ApplyFunctionExpr(function, fnName, (LambdaExpr) nodes.get(ctx.lambda()), (List<Expr>) nodes.get(ctx.fnArgs()))
);
}View on GitHub (pinned to 9b90983fd2)
Solutions
- Fix the expression string to use supported unary operators: '-' for negation and 'NOT' for logical not
- Replace '!' with 'NOT' or restructure the condition
- If the token looks valid, upgrade Druid so grammar and listener match
Example fix
// before "!flag" // after "NOT flag"
Defensive patterns
Strategy: validation
Validate before calling
// validate expression text before parsing
String trimmed = exprStr.trim();
if (trimmed.matches("^!.*") || trimmed.startsWith("~")) {
throw new IllegalArgumentException("unsupported unary operator in: " + exprStr);
} Try / catch
try {
expr = Expr.parse(exprStr);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Unrecognized unary operator")) {
throw new IllegalArgumentException("Invalid expression: " + exprStr, e);
} else { throw e; }
} Prevention
- Use only '-' and 'NOT' for unary operators in native expressions
- Lint/validate user-supplied expressions before parsing
- Pin grammar and listener versions when customizing Druid
When it happens
Trigger: Parsing an expression whose unary operator token isn't '-' or 'NOT', typically via Expr.parse / Parser.parse with malformed or nonstandard unary syntax.
Common situations: Hand-written expressions with invalid unary syntax like '!' (instead of NOT) or stray symbols; grammar/parser version skew after a Druid upgrade; programmatic query builders emitting unsupported tokens.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Unrecognized binary operator %s
- function '%s' is not defined.
- invalid value %s
- Unable to parse line.
- Multiple lines present; unable to parse more than one per re
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/8db992ece56cc91d.
Report an issue: GitHub.