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
- Inspect the predicate SQL and ensure the WHERE clause is a boolean expression (comparisons, AND/OR, IS NULL), not a bare non-boolean value
- Re-run optimization/relaxation so predicates are reduced to boolean RexNodes before reaching IcebergFilter
- Upgrade/verify the Calcite version matches what Beam SQL expects, since type inference is Calcite's job
- 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
- Ensure WHERE clauses evaluate to booleans
- Validate predicates before pushdown
- Keep Calcite versions aligned with Beam
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
- Encountered an unexpected node type
- Attempting to create database
- Attempting to 'USE CATALOG
- Cannot create a filter for an unsupported node
- Encountered an error when parsing filter
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)