{"record":{"id":"ab8ecf030cd8504c","repo":"apache/iceberg","slug":"expected-number-of-buckets-to-be-tinyint-shortint","errorCode":null,"errorMessage":"Expected number of buckets to be tinyint, shortint or int","messagePattern":"Expected number of buckets to be tinyint, shortint or int","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/functions/BucketFunction.java","lineNumber":71,"sourceCode":" * results.\n */\npublic class BucketFunction implements UnboundFunction {\n\n  private static final int NUM_BUCKETS_ORDINAL = 0;\n  private static final int VALUE_ORDINAL = 1;\n\n  private static final Set<DataType> SUPPORTED_NUM_BUCKETS_TYPES =\n      ImmutableSet.of(DataTypes.ByteType, DataTypes.ShortType, DataTypes.IntegerType);\n\n  @Override\n  @SuppressWarnings(\"checkstyle:CyclomaticComplexity\")\n  public BoundFunction bind(StructType inputType) {\n    if (inputType.size() != 2) {\n      throw new UnsupportedOperationException(\n          \"Wrong number of inputs (expected numBuckets and value)\");\n    }\n\n    StructField numBucketsField = inputType.fields()[NUM_BUCKETS_ORDINAL];\n    StructField valueField = inputType.fields()[VALUE_ORDINAL];\n\n    if (!SUPPORTED_NUM_BUCKETS_TYPES.contains(numBucketsField.dataType())) {\n      throw new UnsupportedOperationException(\n          \"Expected number of buckets to be tinyint, shortint or int\");\n    }\n\n    DataType type = valueField.dataType();\n    if (type instanceof DateType) {\n      return new BucketInt(type);\n    } else if (type instanceof ByteType\n        || type instanceof ShortType\n        || type instanceof IntegerType) {\n      return new BucketInt(DataTypes.IntegerType);\n    } else if (type instanceof LongType) {\n      return new BucketLong(type);\n    } else if (type instanceof TimestampType) {\n      return new BucketLong(type);","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/functions/BucketFunction.java#L53-L89","documentation":"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.","triggerScenarios":"Calling system.bucket(numBuckets, value) where numBuckets is a long, decimal, string literal, or non-constant expression typed outside byte/short/int.","commonSituations":"Passing a BIGINT bucket count from a table property fetched as long; passing a string like '8'; passing a decimal computed value.","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"],"exampleFix":"// before\nspark.sql(\"SELECT system.bucket(CAST(8 AS BIGINT), id) FROM tbl\")\n// after\nspark.sql(\"SELECT system.bucket(8, id) FROM tbl\")","handlingStrategy":"validation","validationCode":"-- numBuckets must be BYTE/SHORT/INT\nSELECT system.bucket(CAST(n AS INT), id) FROM tbl;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["spark","sql-functions","bucketing","type-mismatch"],"backgroundTag":"invalid-argument-value","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}