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

  1. Fix the expression so it contains no identifiers — make all inputs literal constants.
  2. If bindings are genuinely needed, use InputBindings.forMap(Map) or a real Expr.ObjectBinding instead of the constant-expr binding.
  3. 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

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.