apache/iceberg · error · UnsupportedOperationException
Expected truncation width to be tinyint, shortint or int
Error message
Expected truncation width to be tinyint, shortint or int
What it means
Iceberg's truncate(value, width) function validates that the width argument is a ByteType, ShortType, or IntegerType. Widths of any other type — long, string, decimal, etc. — cannot define a truncation width, so bind() throws this UnsupportedOperationException during query analysis.
Solutions
- Cast the width to int: truncate(name, CAST(10 AS INT)).
- Use a plain integer literal: truncate(name, 10).
- If width comes from a variable/column, ensure it is declared or cast as int/short/byte.
- Check the argument order — the width must be the second argument.
Example fix
// before SELECT truncate(name, 10L) FROM t // after SELECT truncate(name, CAST(10 AS INT)) FROM t
Defensive patterns
Strategy: validation
Validate before calling
// Spark Scala — before calling truncate()
val width: Any = 10
require(width.isInstanceOf[Integer] || width.isInstanceOf[java.lang.Short] || width.isInstanceOf[java.lang.Byte],
s"truncate width must be int/short/tinyint, got: ${if (width == null) "null" else width.getClass.getSimpleName}") Type guard
def isSupportedWidthType(dt: org.apache.spark.sql.types.DataType): Boolean = dt == org.apache.spark.sql.types.ByteType || dt == org.apache.spark.sql.types.ShortType || dt == org.apache.spark.sql.types.IntegerType
Try / catch
try {
df.select(expr(s"truncate(name, $widthExpr)"))
} catch {
case e: UnsupportedOperationException if e.getMessage.contains("truncation width") =>
throw new IllegalArgumentException("truncate() width must be an int/short/tinyint; cast the width to INT", e)
} Prevention
- Use plain integer literals for width (10, not 10L)
- Cast config- or variable-sourced widths to INT before use
- Avoid string widths from templated SQL — validate they parse to int
- Check argument order: truncate(value, width)
When it happens
Trigger: Calling truncate(value, 10L) with a long literal, truncate(value, width_col) where width_col is long/string/decimal, or truncate(name, '5') with a string width.
Common situations: Long-typed literals from Spark's default integer-literal widening; passing a width parameter from a long-typed config/variable; string widths from templated SQL.
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
- Expected number of buckets to be tinyint, shortint or int
- Expected column to be date, tinyint, smallint, int, bigint…
- Expected column to be date, tinyint, smallint, int, bigint…
- Expected number of buckets to be tinyint, shortint or int
- Expected truncation col to be tinyint, shortint, int…
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/0f5fc50aebde136d.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/functions/TruncateFunction.java:72
public class TruncateFunction implements UnboundFunction {
private static final int WIDTH_ORDINAL = 0;
private static final int VALUE_ORDINAL = 1;
private static final Set<DataType> SUPPORTED_WIDTH_TYPES =
ImmutableSet.of(DataTypes.ByteType, DataTypes.ShortType, DataTypes.IntegerType);
@Override
public BoundFunction bind(StructType inputType) {
if (inputType.size() != 2) {
throw new UnsupportedOperationException("Wrong number of inputs (expected width and value)");
}
StructField widthField = inputType.fields()[WIDTH_ORDINAL];
StructField valueField = inputType.fields()[VALUE_ORDINAL];
if (!SUPPORTED_WIDTH_TYPES.contains(widthField.dataType())) {
throw new UnsupportedOperationException(
"Expected truncation width to be tinyint, shortint or int");
}
DataType valueType = valueField.dataType();
if (valueType instanceof ByteType) {
return new TruncateTinyInt();
} else if (valueType instanceof ShortType) {
return new TruncateSmallInt();
} else if (valueType instanceof IntegerType) {
return new TruncateInt();
} else if (valueType instanceof LongType) {
return new TruncateBigInt();
} else if (valueType instanceof DecimalType) {
return new TruncateDecimal(
((DecimalType) valueType).precision(), ((DecimalType) valueType).scale());
} else if (valueType instanceof StringType) {
return new TruncateString();
} else if (valueType instanceof BinaryType) {View on GitHub (pinned to 86d9c8fc54)