apache/iceberg · error · IllegalStateException

Invalid operation for BoundLiteralPredicate:

Error message

Invalid operation for BoundLiteralPredicate: 

What it means

BoundLiteralPredicate.test(...) supports only literal-comparison operations (LT, LT_EQ, GT, GT_EQ, EQ, NOT_EQ, STARTS_WITH, NOT_STARTS_WITH). Any other operation (e.g. IS_NULL / IN, which belong to other predicate classes) reaching the switch throws this IllegalStateException.

Source

Thrown at api/src/main/java/org/apache/iceberg/expressions/BoundLiteralPredicate.java:92

    switch (op()) {
      case LT:
        return cmp.compare(value, literal.value()) < 0;
      case LT_EQ:
        return cmp.compare(value, literal.value()) <= 0;
      case GT:
        return cmp.compare(value, literal.value()) > 0;
      case GT_EQ:
        return cmp.compare(value, literal.value()) >= 0;
      case EQ:
        return cmp.compare(value, literal.value()) == 0;
      case NOT_EQ:
        return cmp.compare(value, literal.value()) != 0;
      case STARTS_WITH:
        return String.valueOf(value).startsWith((String) literal.value());
      case NOT_STARTS_WITH:
        return !String.valueOf(value).startsWith((String) literal.value());
      default:
        throw new IllegalStateException("Invalid operation for BoundLiteralPredicate: " + op());
    }
  }

  @Override
  @SuppressWarnings("unchecked")
  public boolean isEquivalentTo(Expression expr) {
    if (op() == expr.op()) {
      BoundLiteralPredicate<?> other = (BoundLiteralPredicate<?>) expr;
      if (term().isEquivalentTo(other.term())) {
        // because the term is equivalent, the literal must have the same type, T
        Literal<T> otherLiteral = (Literal<T>) other.literal();
        Comparator<T> cmp = literal.comparator();
        return cmp.compare(literal.value(), otherLiteral.value()) == 0;
      }

    } else if (expr instanceof BoundLiteralPredicate) {
      BoundLiteralPredicate<?> other = (BoundLiteralPredicate<?>) expr;
      if (INTEGRAL_TYPES.contains(term().type().typeId()) && term().isEquivalentTo(other.term())) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check pred.isLiteralPredicate() and op() before casting/calling test
  2. Route IS_NULL/NOT_NULL to BoundUnaryPredicate and IN/NOT_IN to BoundSetPredicate
  3. Use ExpressionVisitors.predicates() dispatch instead of manual casts

Example fix

// before
BoundLiteralPredicate lit = (BoundLiteralPredicate) pred; // may be IS_NULL etc.
boolean r = lit.test(value); // throws for non-literal ops
// after
if (pred.isLiteralPredicate()) {
  BoundLiteralPredicate lit = (BoundLiteralPredicate) pred;
  boolean r = lit.test(value);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (pred.isLiteralPredicate()) { Set.of(Operation.LT, Operation.LT_EQ, Operation.GT, Operation.GT_EQ, Operation.EQ, Operation.NOT_EQ, Operation.STARTS_WITH, Operation.NOT_STARTS_WITH).contains(pred.op()); }

Type guard

if (pred instanceof BoundLiteralPredicate lit && Set.of(Operation.EQ, Operation.LT, Operation.GT).contains(lit.op())) { /* safe to test */ }

Try / catch

try { r = lit.test(value); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Invalid operation for BoundLiteralPredicate")) { /* dispatch to unary/set predicate path */ } else { throw e; } }

Prevention

When it happens

Trigger: Calling test(value) or matchLiteral on a BoundLiteralPredicate whose op is a non-literal operation, usually after incorrect casting of a generic BoundPredicate to BoundLiteralPredicate without checking isLiteralPredicate().

Common situations: Custom predicate evaluation that casts predicates without narrowing; expression rewriting that swaps operations while keeping the literal predicate class.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/146abab13753ae37. Report an issue: GitHub.