apache/iceberg · error · UnsupportedOperationException

Unsupported predicate operation

Error message

Unsupported predicate operation: <op>

What it means

The private pred() helper maps a bound predicate operation (EQ, NOT_EQ, GT, GT_EQ, LT, LT_EQ) to the corresponding Parquet FilterApi call. Any other operation reaching the default branch is rejected with this UnsupportedOperationException. It is a guard against operations the Parquet column-index filter API cannot express.

Solutions

  1. Use only comparison operators (==, !=, <, <=, >, >=) in expressions intended for Parquet pushdown
  2. Rewrite IN as an OR of equalities, or handle the predicate client-side instead of pushdown
  3. Catch UnsupportedOperationException and skip pushdown for that filter

Example fix

// before
Expression e = Expressions.startsWith("name", "A");
FilterPredicate p = ParquetFilters.predicate(binder.bind(schema, e)); // throws
// after
Expression e = Expressions.equal("name", "Alice");
FilterPredicate p = ParquetFilters.predicate(binder.bind(schema, e));
Defensive patterns

Strategy: validation

Validate before calling

switch (pred.op()) {
  case EQ: case NOT_EQ: case GT: case GT_EQ: case LT: case LT_EQ: break;
  default: throw new IllegalArgumentException("Not Parquet-pushdownable: " + pred.op());
}

Try / catch

try {
  FilterPredicate p = ParquetFilters.predicate(bound);
} catch (UnsupportedOperationException e) {
  logger.warn("Skipping pushdown: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling ParquetFilters.predicate() with a bound predicate whose operation is not one of EQ, NOT_EQ, GT, GT_EQ, LT, LT_EQ — e.g. STARTS_WITH, IN, or IS_NULL bound predicates that reach the pred() helper.

Common situations: Pushing down string startsWith filters, IN-list filters, or null checks on a Parquet scan; using expression types from a newer Iceberg version with an older converter.

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/ead618cfbd8d9e4f. Report an issue: GitHub.

Appendix: source

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

        } else if (col.getColumnType().equals(Float.class)) {
          return FilterApi.notEq(col, (C) (Float) Float.NaN);
        } else {
          return AlwaysTrue.INSTANCE;
        }
      case EQ:
        return FilterApi.eq(col, value);
      case NOT_EQ:
        return FilterApi.notEq(col, value);
      case GT:
        return FilterApi.gt(col, value);
      case GT_EQ:
        return FilterApi.gtEq(col, value);
      case LT:
        return FilterApi.lt(col, value);
      case LT_EQ:
        return FilterApi.ltEq(col, value);
      default:
        throw new UnsupportedOperationException("Unsupported predicate operation: " + op);
    }
  }

  @SuppressWarnings("unchecked")
  private static <C extends Comparable<C>> C getParquetPrimitive(Literal<?> lit) {
    if (lit == null) {
      return null;
    }

    // TODO: this needs to convert to handle BigDecimal and UUID
    Object value = lit.value();
    if (value instanceof Number) {
      return (C) lit.value();
    } else if (value instanceof CharSequence) {
      return (C) Binary.fromString(value.toString());
    } else if (value instanceof ByteBuffer) {
      return (C) Binary.fromReusedByteBuffer((ByteBuffer) value);
    }

View on GitHub (pinned to 86d9c8fc54)