apache/beam · error · IllegalArgumentException

Predicate node ' ' should be a boolean expression, but was

Error message

Predicate node '${nodeClass}' should be a boolean expression, but was: ${sqlTypeName}

What it means

IcebergCatalog/SQL predicate pushdown requires every CNF conjunct to be a BOOLEAN-typed RexNode. During filter initialization, if a predicate node's SqlTypeName is not BOOLEAN, Calcite cannot interpret it as a filter condition, so the code throws immediately to prevent generating a wrong filter.

Solutions

  1. Inspect the predicate SQL and ensure the WHERE clause is a boolean expression (comparisons, AND/OR, IS NULL), not a bare non-boolean value
  2. Re-run optimization/relaxation so predicates are reduced to boolean RexNodes before reaching IcebergFilter
  3. Upgrade/verify the Calcite version matches what Beam SQL expects, since type inference is Calcite's job
  4. If you construct RexNodes programmatically, wrap the expression in a boolean comparison instead of passing a raw value node

Example fix

// before
String sql = "SELECT * FROM tbl WHERE int_col";
// after
String sql = "SELECT * FROM tbl WHERE int_col > 0";
Defensive patterns

Strategy: validation

Validate before calling

if (!node.getType().getSqlTypeName().equals(SqlTypeName.BOOLEAN)) {
  throw new IllegalArgumentException("Predicate must be boolean: " + node);
}

Type guard

boolean isBooleanPredicate(RexNode n) { return n.getType().getSqlTypeName().equals(SqlTypeName.BOOLEAN); }

Prevention

When it happens

Trigger: Calling getSupported/numSupported/getNotSupported on an IcebergTable filter where the pushed-down predicate CNF contains a node whose type is not SqlTypeName.BOOLEAN (e.g. an INT comparison result or untyped literal slipped through optimization).

Common situations: Custom or malformed predicates passed to Iceberg SQL pushdown, Calcite planner changes that leave non-boolean nodes in the CNF, hand-built RexNode trees in tests or custom table providers.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/357ed8c992a4b3da. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/extensions/sql/iceberg/src/main/java/org/apache/beam/sdk/extensions/sql/meta/provider/iceberg/IcebergFilter.java:56

public class IcebergFilter implements BeamSqlTableFilter {
  private @Nullable List<RexNode> supported;
  private @Nullable List<RexNode> unsupported;
  private final List<RexNode> predicateCNF;

  public IcebergFilter(List<RexNode> predicateCNF) {
    this.predicateCNF = predicateCNF;
  }

  private void maybeInitialize() {
    if (supported != null && unsupported != null) {
      return;
    }
    ImmutableList.Builder<RexNode> supportedBuilder = ImmutableList.builder();
    ImmutableList.Builder<RexNode> unsupportedBuilder = ImmutableList.builder();
    for (RexNode node : predicateCNF) {
      if (!node.getType().getSqlTypeName().equals(SqlTypeName.BOOLEAN)) {
        throw new IllegalArgumentException(
            "Predicate node '"
                + node.getClass().getSimpleName()
                + "' should be a boolean expression, but was: "
                + node.getType().getSqlTypeName());
      }

      if (isSupported(node).getLeft()) {
        supportedBuilder.add(node);
      } else {
        unsupportedBuilder.add(node);
      }
    }
    supported = supportedBuilder.build();
    unsupported = unsupportedBuilder.build();
  }

  @Override
  public List<RexNode> getNotSupported() {

View on GitHub (pinned to 12126d8942)