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.

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.

Appendix: 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)