apache/iceberg · error · UnsupportedOperationException

Cannot convert to Parquet filter

Error message

Cannot convert to Parquet filter: <pred>

What it means

Thrown when a bound predicate is neither a unary predicate (no literal) nor a literal predicate, so the translator cannot extract a Parquet Literal to build the FilterPredicate. Only unary ops (is-null/not-null) and literal comparisons are convertible; other bound predicate kinds are not.

Solutions

  1. Restrict pushdown to simple literal/unary predicates on primitive columns; filter the expression tree before calling the translator.
  2. Rewrite unsupported predicates into supported equivalents at planning time.
  3. Upgrade Iceberg for broader predicate coverage.

Example fix

// before
pushdown(customNonLiteralPredicate("col")); // non-convertible
// after
pushdown(Expressions.notNull("col")); // unary predicate, convertible
Defensive patterns

Strategy: validation

Validate before calling

if (!(pred.isUnaryPredicate() || pred.isLiteralPredicate())) {
  // leave for record-level evaluation; do not push down
}

Type guard

boolean convertible(BoundPredicate<?> pred) {
  return pred.isUnaryPredicate() || pred.isLiteralPredicate();
}

Try / catch

try {
  FilterPredicate fp = parquetFilters.predicate(pred);
} catch (UnsupportedOperationException e) {
  LOG.debug("Skip pushdown: {}", e.getMessage());
  return null; // evaluate rows instead
}

Prevention

When it happens

Trigger: Pushing predicates with complex/transformed terms or non-literal predicate kinds into this translator's predicate(BoundPredicate) method.

Common situations: Custom expression trees; engine versions generating new predicate kinds the translator predates; filters built programmatically with unusual ops.

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/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/9635f879ac59145b. Report an issue: GitHub.

Appendix: source

Thrown at parquet/src/main/java/org/apache/iceberg/parquet/ParquetFilters.java:127

    }

    @Override
    public <T> FilterPredicate predicate(BoundPredicate<T> pred) {
      if (!(pred.term() instanceof BoundReference)) {
        throw new UnsupportedOperationException(
            "Cannot convert non-reference to Parquet filter: " + pred.term());
      }

      Operation op = pred.op();
      BoundReference<T> ref = (BoundReference<T>) pred.term();
      String path = schema.idToAlias(ref.fieldId());
      Literal<T> lit;
      if (pred.isUnaryPredicate()) {
        lit = null;
      } else if (pred.isLiteralPredicate()) {
        lit = pred.asLiteralPredicate().literal();
      } else {
        throw new UnsupportedOperationException("Cannot convert to Parquet filter: " + pred);
      }

      switch (ref.type().typeId()) {
        case BOOLEAN:
          Operators.BooleanColumn col = FilterApi.booleanColumn(path);
          switch (op) {
            case EQ:
              return FilterApi.eq(col, getParquetPrimitive(lit));
            case NOT_EQ:
              return FilterApi.notEq(col, getParquetPrimitive(lit));
          }
          break;
        case INTEGER:
        case DATE:
          return pred(op, FilterApi.intColumn(path), getParquetPrimitive(lit));
        case LONG:
        case TIME:
        case TIMESTAMP:

View on GitHub (pinned to 86d9c8fc54)