apache/iceberg · error

Cannot truncate type: + type

Error message

Cannot truncate type: + type

What it means

Thrown by Truncate.get(Function applied to a type) when the target type is not one of the truncatable types — INTEGER/LONG (integers), DECIMAL, STRING, or BINARY. Truncation is only defined for those types; attempting to truncate e.g. a DATE, TIMESTAMP, or FLOAT fails fast rather than producing undefined behavior.

Source

Thrown at api/src/main/java/org/apache/iceberg/transforms/Truncate.java:66

   */
  @Deprecated
  @SuppressWarnings("unchecked")
  static <T, R extends Truncate<T> & SerializableFunction<T, T>> R get(Type type, int width) {
    Preconditions.checkArgument(width > 0, "Invalid truncate width: %s (must be > 0)", width);

    switch (type.typeId()) {
      case INTEGER:
        return (R) new TruncateInteger(width);
      case LONG:
        return (R) new TruncateLong(width);
      case DECIMAL:
        return (R) new TruncateDecimal(width);
      case STRING:
        return (R) new TruncateString(width);
      case BINARY:
        return (R) new TruncateByteBuffer(width);
      default:
        throw new UnsupportedOperationException("Cannot truncate type: " + type);
    }
  }

  @SuppressWarnings("checkstyle:VisibilityModifier")
  protected final int width;

  Truncate(int width) {
    this.width = width;
  }

  public Integer width() {
    return width;
  }

  @Override
  public T apply(T value) {
    throw new UnsupportedOperationException(
        "apply(value) is deprecated, use bind(Type).apply(value)");

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Only apply Truncate to INTEGER, LONG, DECIMAL, STRING, or BINARY columns
  2. Check transform.canTransform(type) before binding and reject unsupported types with a clear message
  3. Use the dedicated timestamp transforms (day/hour/etc.) for temporal columns instead of truncate

Example fix

// before
Transforms.truncate(10).bind(TimestampType.get()); // throws
// after
Transforms.hour("ts"); // or truncate on a string/binary/int column
Defensive patterns

Strategy: validation

Validate before calling

if (!truncateTransform.canTransform(columnType)) {
  throw new IllegalArgumentException("Cannot truncate type: " + columnType + "; use int/long/decimal/string/binary");
}

Type guard

boolean truncatable(Type t) {
  return t.typeId() == Type.TypeID.INTEGER || t.typeId() == Type.TypeID.LONG
      || t.typeId() == Type.TypeID.DECIMAL || t.typeId() == Type.TypeID.STRING
      || t.typeId() == Type.TypeID.BINARY;
}

Try / catch

try { fn = truncate.bind(type); } catch (UnsupportedOperationException e) { /* choose day()/hour() for temporal, or reject the spec */ }

Prevention

When it happens

Trigger: Calling Truncate.of(width).bind(type) (which internally invokes get) with a type outside {IntegerType, LongType, DecimalType, StringType, BinaryType} — e.g. binding truncate to TimestampType or FloatType.

Common situations: Building a partition spec that truncates a timestamp or float column; dynamic spec construction where the column type comes from user input without validating truncatability.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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