{"record":{"id":"0f5fc50aebde136d","repo":"apache/iceberg","slug":"expected-truncation-width-to-be-tinyint-shortint-0f5fc5","errorCode":null,"errorMessage":"Expected truncation width to be tinyint, shortint or int","messagePattern":"Expected truncation width to be tinyint, shortint or int","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/functions/TruncateFunction.java","lineNumber":72,"sourceCode":"public class TruncateFunction implements UnboundFunction {\n\n  private static final int WIDTH_ORDINAL = 0;\n  private static final int VALUE_ORDINAL = 1;\n\n  private static final Set<DataType> SUPPORTED_WIDTH_TYPES =\n      ImmutableSet.of(DataTypes.ByteType, DataTypes.ShortType, DataTypes.IntegerType);\n\n  @Override\n  public BoundFunction bind(StructType inputType) {\n    if (inputType.size() != 2) {\n      throw new UnsupportedOperationException(\"Wrong number of inputs (expected width and value)\");\n    }\n\n    StructField widthField = inputType.fields()[WIDTH_ORDINAL];\n    StructField valueField = inputType.fields()[VALUE_ORDINAL];\n\n    if (!SUPPORTED_WIDTH_TYPES.contains(widthField.dataType())) {\n      throw new UnsupportedOperationException(\n          \"Expected truncation width to be tinyint, shortint or int\");\n    }\n\n    DataType valueType = valueField.dataType();\n    if (valueType instanceof ByteType) {\n      return new TruncateTinyInt();\n    } else if (valueType instanceof ShortType) {\n      return new TruncateSmallInt();\n    } else if (valueType instanceof IntegerType) {\n      return new TruncateInt();\n    } else if (valueType instanceof LongType) {\n      return new TruncateBigInt();\n    } else if (valueType instanceof DecimalType) {\n      return new TruncateDecimal(\n          ((DecimalType) valueType).precision(), ((DecimalType) valueType).scale());\n    } else if (valueType instanceof StringType) {\n      return new TruncateString();\n    } else if (valueType instanceof BinaryType) {","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/functions/TruncateFunction.java#L54-L90","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nSELECT truncate(name, 10L) FROM t\n// after\nSELECT truncate(name, CAST(10 AS INT)) FROM t","handlingStrategy":"validation","validationCode":"// Spark Scala — before calling truncate()\nval width: Any = 10\nrequire(width.isInstanceOf[Integer] || width.isInstanceOf[java.lang.Short] || width.isInstanceOf[java.lang.Byte],\n  s\"truncate width must be int/short/tinyint, got: ${if (width == null) \"null\" else width.getClass.getSimpleName}\")","typeGuard":"def isSupportedWidthType(dt: org.apache.spark.sql.types.DataType): Boolean =\n  dt == org.apache.spark.sql.types.ByteType ||\n  dt == org.apache.spark.sql.types.ShortType ||\n  dt == org.apache.spark.sql.types.IntegerType","tryCatchPattern":"try {\n  df.select(expr(s\"truncate(name, $widthExpr)\"))\n} catch {\n  case e: UnsupportedOperationException if e.getMessage.contains(\"truncation width\") =>\n    throw new IllegalArgumentException(\"truncate() width must be an int/short/tinyint; cast the width to INT\", e)\n}","preventionTips":["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)"],"tags":["spark","sql-function","type-mismatch","bind"],"backgroundTag":"type-mismatch","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}