apache/iceberg · error · ValidationException

IsNaN cannot be used with a non-floating-point column

Error message

IsNaN cannot be used with a non-floating-point column

What it means

Iceberg's IS_NAN predicate is only meaningful for float and double columns. When an UnboundPredicate with Operation.IS_NAN is bound against a struct whose term resolves to a non-floating-point type, binding fails with this ValidationException rather than producing a predicate that can never be true.

Source

Thrown at api/src/main/java/org/apache/iceberg/expressions/UnboundPredicate.java:148

            && allAncestorFieldsAreRequired(struct, boundTerm.ref().fieldId())) {
          return Expressions.alwaysFalse();
        } else if (boundTerm.type().equals(Types.UnknownType.get())) {
          return Expressions.alwaysTrue();
        }
        return new BoundUnaryPredicate<>(Operation.IS_NULL, boundTerm);
      case NOT_NULL:
        if (!boundTerm.producesNull()
            && allAncestorFieldsAreRequired(struct, boundTerm.ref().fieldId())) {
          return Expressions.alwaysTrue();
        } else if (boundTerm.type().equals(Types.UnknownType.get())) {
          return Expressions.alwaysFalse();
        }
        return new BoundUnaryPredicate<>(Operation.NOT_NULL, boundTerm);
      case IS_NAN:
        if (floatingType(boundTerm.type().typeId())) {
          return new BoundUnaryPredicate<>(Operation.IS_NAN, boundTerm);
        } else {
          throw new ValidationException("IsNaN cannot be used with a non-floating-point column");
        }
      case NOT_NAN:
        if (floatingType(boundTerm.type().typeId())) {
          return new BoundUnaryPredicate<>(Operation.NOT_NAN, boundTerm);
        } else {
          throw new ValidationException("NotNaN cannot be used with a non-floating-point column");
        }
      default:
        throw new ValidationException("Operation must be IS_NULL, NOT_NULL, IS_NAN, or NOT_NAN");
    }
  }

  private boolean allAncestorFieldsAreRequired(StructType struct, int fieldId) {
    return TypeUtil.ancestorFields(struct.asSchema(), fieldId).stream()
        .allMatch(Types.NestedField::isRequired);
  }

  private boolean floatingType(Type.TypeID typeID) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Use isNaN only for float/double columns; use isNull for other types
  2. Check the field type in the table schema before building the predicate and choose the operation accordingly
  3. Fix the query/filter to target the correct column or drop the NaN check for non-float columns

Example fix

// before
Expression e = Expressions.isNaN("int_col");
// after
Types.NestedField f = schema.findField("int_col");
Expression e = (f.type().typeId() == Type.TypeID.FLOAT || f.type().typeId() == Type.TypeID.DOUBLE)
    ? Expressions.isNaN("int_col")
    : Expressions.isNull("int_col");
Defensive patterns

Strategy: validation

Validate before calling

Type t = schema.findType("col");
boolean ok = t instanceof Types.FloatType || t instanceof Types.DoubleType;
if (!ok) throw new IllegalArgumentException("isNaN requires float/double column");

Type guard

static boolean isFloating(Type t) { return t.typeId() == Type.TypeID.FLOAT || t.typeId() == Type.TypeID.DOUBLE; }

Try / catch

try { Expression bound = Binder.bind(struct, Expressions.isNaN("col"), true); } catch (ValidationException e) { /* fall back to isNull or reject the filter */ }

Prevention

When it happens

Trigger: Expressions.isNull/isNaN-style filter: e.g. Expressions.isNaN("int_col") or filter("isNaN(id)") where the referenced field is int, long, decimal, string, timestamp, etc., then binding the expression to a table schema.

Common situations: User-submitted SQL with IS NAN on integer columns; query builders that emit isNaN generically for numeric fields; schema evolution changing a column from double to a non-float type while old NaN filters remain.

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