apache/beam · error · IllegalArgumentException

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

Error message

Predicate node '%s' should be a boolean expression, but was: %s

What it means

The BigQueryFilter constructor validates that every predicate in the CNF (conjunctive normal form) list is a boolean-typed expression. If any RexNode's type is not SqlTypeName.BOOLEAN — meaning a non-boolean expression was handed to the pushdown filter builder — it throws IllegalArgumentException identifying the node and its actual SQL type.

Solutions

  1. Pass only boolean predicates (comparisons, AND/OR of comparisons) into BigQueryFilter
  2. Filter the CNF list to nodes whose getType().getSqlTypeName() == SqlTypeName.BOOLEAN before constructing
  3. Check how predicates are extracted (RexUtil/condition splitting) to avoid pulling non-condition expressions into the CNF

Example fix

// before
new BigQueryFilter(allProjectExpressions)
// after
List<RexNode> booleanPreds = allProjectExpressions.stream()
    .filter(n -> n.getType().getSqlTypeName().equals(SqlTypeName.BOOLEAN))
    .collect(Collectors.toList());
new BigQueryFilter(booleanPreds)
Defensive patterns

Strategy: validation

Validate before calling

// before constructing
boolean allBoolean = predicateCNF.stream()
    .allMatch(n -> n.getType().getSqlTypeName().equals(SqlTypeName.BOOLEAN));
if (!allBoolean) throw new IllegalArgumentException("CNF list must contain only boolean predicates");

Type guard

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

Try / catch

try {
  BigQueryFilter f = new BigQueryFilter(cnf);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("should be a boolean expression")) { /* sanitize inputs and retry */ }
  throw e;
}

Prevention

When it happens

Trigger: Constructing BigQueryFilter with a List<RexNode> predicateCNF that includes a non-boolean node, e.g. a literal, arithmetic result, or column reference of type INTEGER/VARCHAR instead of a comparison.

Common situations: Building filter pushdown pipelines where CNF extraction accidentally includes projected (non-filter) expressions; custom rel nodes passing raw operands rather than boolean conjunctions; optimizer rewrites changing node types.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/meta/provider/bigquery/BigQueryFilter.java:64

  "nullness" // TODO(https://github.com/apache/beam/issues/20497)
})
public class BigQueryFilter implements BeamSqlTableFilter {
  private static final ImmutableSet<SqlKind> SUPPORTED_OPS =
      ImmutableSet.<SqlKind>builder()
          .add(COMPARISON.toArray(new SqlKind[0]))
          // TODO: Check what other functions are supported and add support for them (ex: trim).
          .add(PLUS, MINUS, MOD, DIVIDE, TIMES, LIKE, BETWEEN, CAST, AND, OR)
          .build();
  private List<RexNode> supported;
  private List<RexNode> unsupported;

  public BigQueryFilter(List<RexNode> predicateCNF) {
    supported = new ArrayList<>();
    unsupported = new ArrayList<>();

    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()) {
        supported.add(node);
      } else {
        unsupported.add(node);
      }
    }
  }

  @Override
  public List<RexNode> getNotSupported() {
    return unsupported;
  }

View on GitHub (pinned to 12126d8942)