apache/druid · error · UOE
Expression %s has non-constant inputs.
Error message
Expression %s has non-constant inputs.
What it means
InputBindings.forMapWithConstantExpr creates an Expr.InputBindingInspector whose get() can never supply inputs; it exists only for constant expressions. If expression evaluation or planning asks this binding for an input identifier, the code treats it as a programming error and throws UOE (Unsupported Operation Exception). It is a sanity-check guard, not a user-input validation.
Source
Thrown at processing/src/main/java/org/apache/druid/math/expr/InputBindings.java:73
*/
public static Expr.ObjectBinding nilBindings()
{
return NIL_BINDINGS;
}
/**
* Empty binding that throw a {@link UOE} if anything attempts to lookup an identifier type or value
*/
public static Expr.ObjectBinding validateConstant(Expr expr)
{
return new Expr.ObjectBinding()
{
@Nullable
@Override
public Object get(String name)
{
// Sanity check. Bindings should not be used for a constant expression so explode if something tried
throw new UOE("Expression " + expr.stringify() + " has non-constant inputs.");
}
@Nullable
@Override
public ExpressionType getType(String name)
{
// Sanity check. Bindings should not be used for a constant expression so explode if something tried
throw new UOE("Expression " + expr.stringify() + " has non-constant inputs.");
}
};
}
/**
* Create an {@link Expr.InputBindingInspector} backed by a map of binding identifiers to their {@link ExprType}
*/
public static Expr.InputBindingInspector inspectorFromTypeMap(final Map<String, ExpressionType> types)
{
return new Expr.InputBindingInspector()View on GitHub (pinned to 9b90983fd2)
Solutions
- Fix the expression so it contains no identifiers — make all inputs literal constants.
- If bindings are genuinely needed, use InputBindings.forMap(Map) or a real Expr.ObjectBinding instead of the constant-expr binding.
- Check the caller that supplies the Expr; ensure only constant expressions are routed through the constant-binding path.
Example fix
// before
Expr e = Parser.parse("x + 1", null);
eval(e, InputBindings.forMapWithConstantExpr(e));
// after
Expr e = Parser.parse("1 + 1", null); // or use InputBindings.forMap(Map.of("x", 1))
eval(e, InputBindings.forMap(Map.of("x", 1))); Defensive patterns
Strategy: validation
Validate before calling
if (!expr.analyzeInputs().getRequiredBindings().isEmpty()) {
throw new IllegalArgumentException("expression must be constant for constant bindings: " + expr.stringify());
} Try / catch
try { eval(expr, InputBindings.forMapWithConstantExpr(expr)); } catch (UnsupportedOperationException e) { /* fall back to map-backed bindings */ } Prevention
- Only route expressions verified to have zero required bindings through constant bindings
- Prefer InputBindings.forMap as the default binding choice
- Unit-test expression constants with representative inputs
When it happens
Trigger: Calling Parser.parse(..., true) and then evaluating/planning the resulting Expr with constant bindings (InputBindings.forMapWithConstantExpr) when the expression actually references identifiers (e.g. "x + 1" instead of "1 + 1"). The get(String) binding accessor is then invoked for identifier 'x'.
Common situations: Precomputing a constant-folded expression during query planning; using expressions intended to be literal-only (e.g. timestamp math constants) but accidentally passing a column/variable reference; refactoring that changed a literal expression into one with bindings.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/38ddcb766d9b4863.
Report an issue: GitHub.