apache/iceberg · error · UnsupportedOperationException

Expected column to be date, tinyint, smallint, int, bigint,

Error message

Expected column to be date, tinyint, smallint, int, bigint, decimal, timestamp, string, or binary

What it means

Type validation in BucketFunction.bind: the second argument (the value to hash) is not one of the hashable types (date, tinyint, smallint, int, bigint, decimal, timestamp, string, binary). The %s names the value field; note codegen does not re-validate, so the bound type must truly be hashable.

Source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/functions/BucketFunction.java:103

      return new BucketInt(type);
    } else if (type instanceof ByteType
        || type instanceof ShortType
        || type instanceof IntegerType) {
      return new BucketInt(DataTypes.IntegerType);
    } else if (type instanceof LongType) {
      return new BucketLong(type);
    } else if (type instanceof TimestampType) {
      return new BucketLong(type);
    } else if (type instanceof TimestampNTZType) {
      return new BucketLong(type);
    } else if (type instanceof DecimalType) {
      return new BucketDecimal(type);
    } else if (type instanceof StringType) {
      return new BucketString();
    } else if (type instanceof BinaryType) {
      return new BucketBinary();
    } else {
      throw new UnsupportedOperationException(
          "Expected column to be date, tinyint, smallint, int, bigint, decimal, timestamp, string, or binary");
    }
  }

  @Override
  public String description() {
    return name()
        + "(numBuckets, col) - Call Iceberg's bucket transform\n"
        + "  numBuckets :: number of buckets to divide the rows into, e.g. bucket(100, 34) -> 79 (must be a tinyint, smallint, or int)\n"
        + "  col :: column to bucket (must be a date, integer, long, timestamp, decimal, string, or binary)";
  }

  @Override
  public String name() {
    return "bucket";
  }

  public abstract static class BucketBase extends BaseScalarFunction<Integer>

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Bucket a supported column instead (int/bigint key, string, etc.)
  2. Cast the value to a supported type before bucketing, e.g. system.bucket(8, CAST(flag AS INT))
  3. For float/double keys, round/encode to decimal or bigint first: system.bucket(8, CAST(x AS DECIMAL(18,6)))

Example fix

// before
SELECT system.bucket(8, is_active) FROM t;   -- boolean unsupported
// after
SELECT system.bucket(8, CAST(is_active AS INT)) FROM t;
Defensive patterns

Strategy: type-guard

Validate before calling

java.util.Set<DataType> ok = Set.of(DateType, ByteType, ShortType, IntegerType, LongType, DecimalType.USER_DEFAULT, TimestampType, StringType, BinaryType);
if (!ok.contains(valueCol.dataType())) throw new IllegalArgumentException("Unsupported bucket value type: " + valueCol.dataType());

Type guard

boolean bucketable(DataType t) {
  return t instanceof DateType || t instanceof ByteType || t instanceof ShortType || t instanceof IntegerType
    || t instanceof LongType || t instanceof DecimalType || t instanceof TimestampType
    || t instanceof StringType || t instanceof BinaryType;
}

Try / catch

try {
  bound = bucketFn.bind(inputType);
} catch (UnsupportedOperationException e) {
  throw new IllegalArgumentException("Cast the value column to a bucketable type", e);
}

Prevention

When it happens

Trigger: Calling system.bucket(n, <column>) where the column is a float, double, boolean, struct, array, map, or another unsupported type.

Common situations: Bucketing float/double columns (e.g. price); bucketing nested types; bucketing boolean flags; tables where the transform column type evolved to an unsupported type.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/ad5a76074a5805ba. Report an issue: GitHub.