apache/iceberg · error · UnsupportedOperationException
Expected number of buckets to be tinyint, shortint or int
Error message
Expected number of buckets to be tinyint, shortint or int
What it means
Input validation in BucketFunction.bind: the first argument (number of buckets) has a Spark type outside the allowed set {byte, short, int}; the %s names the field. Note the companion guard rejects arity != 2 first, and per the Javadoc the bucket count is not re-validated in codegen, so it must be positive to be meaningful.
Source
Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/functions/BucketFunction.java:71
* results.
*/
public class BucketFunction implements UnboundFunction {
private static final int NUM_BUCKETS_ORDINAL = 0;
private static final int VALUE_ORDINAL = 1;
private static final Set<DataType> SUPPORTED_NUM_BUCKETS_TYPES =
ImmutableSet.of(DataTypes.ByteType, DataTypes.ShortType, DataTypes.IntegerType);
@Override
@SuppressWarnings("checkstyle:CyclomaticComplexity")
public BoundFunction bind(StructType inputType) {
if (inputType.size() != 2) {
throw new UnsupportedOperationException(
"Wrong number of inputs (expected numBuckets and value)");
}
StructField numBucketsField = inputType.fields()[NUM_BUCKETS_ORDINAL];
StructField valueField = inputType.fields()[VALUE_ORDINAL];
if (!SUPPORTED_NUM_BUCKETS_TYPES.contains(numBucketsField.dataType())) {
throw new UnsupportedOperationException(
"Expected number of buckets to be tinyint, shortint or int");
}
DataType type = valueField.dataType();
if (type instanceof DateType) {
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);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Cast the bucket count to INT: system.bucket(CAST(n AS INT), value)
- Use a plain integer literal: system.bucket(8, value)
- If it comes from a long variable, narrow it with Int.satisfied or an explicit cast in Scala/Java code before invoking the function builder
Example fix
// before
spark.sql("SELECT system.bucket(CAST(8 AS BIGINT), id) FROM tbl")
// after
spark.sql("SELECT system.bucket(8, id) FROM tbl") Defensive patterns
Strategy: validation
Validate before calling
-- numBuckets must be BYTE/SHORT/INT SELECT system.bucket(CAST(n AS INT), id) FROM tbl;
Prevention
- Cast bucket counts loaded from properties (often longs) to INT
- Use integer literals for bucket counts
- Check the resolved type with df.schema before executing generated SQL
When it happens
Trigger: Calling system.bucket(numBuckets, value) where numBuckets is a long, decimal, string literal, or non-constant expression typed outside byte/short/int.
Common situations: Passing a BIGINT bucket count from a table property fetched as long; passing a string like '8'; passing a decimal computed value.
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
- Wrong number of inputs (expected numBuckets and value)
- Expected column to be date, tinyint, smallint, int, bigint,
- Expected value to be date or timestamp: ${valueType.catalogS
- Expected value to be timestamp: ${valueType.catalogString()}
- Expected value to be date or timestamp: ${valueType.catalogS
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/ab8ecf030cd8504c.
Report an issue: GitHub.