apache/iceberg · error · IllegalArgumentException

Cannot bucket by type:

Error message

Cannot bucket by type: 

What it means

Bucket.get(Type, int) only supports bucketing source types that Iceberg defines bucket transforms for (int, long, date, time, timestamp, timestamptz, string, uuid, decimal, ByteBuffer variants, timestamp nanos). Requesting a bucket function for any other type hits the default branch and throws IllegalArgumentException. This is a programming/spec error: the requested type is not bucketable.

Source

Thrown at api/src/main/java/org/apache/iceberg/transforms/Bucket.java:78

      case INTEGER:
        return (B) new BucketInteger(numBuckets);
      case TIME:
      case TIMESTAMP:
      case LONG:
        return (B) new BucketLong(numBuckets);
      case DECIMAL:
        return (B) new BucketDecimal(numBuckets);
      case STRING:
        return (B) new BucketString(numBuckets);
      case FIXED:
      case BINARY:
        return (B) new BucketByteBuffer(numBuckets);
      case TIMESTAMP_NANO:
        return (B) new BucketTimestampNano(numBuckets);
      case UUID:
        return (B) new BucketUUID(numBuckets);
      default:
        throw new IllegalArgumentException("Cannot bucket by type: " + type);
    }
  }

  private final int numBuckets;

  private Bucket(int numBuckets) {
    this.numBuckets = numBuckets;
  }

  public Integer numBuckets() {
    return numBuckets;
  }

  @Override
  public SerializableFunction<T, Integer> bind(Type type) {
    Preconditions.checkArgument(canTransform(type), "Cannot bucket by type: %s", type);
    return get(type, numBuckets);
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check Bucket.get(Type).contains(type) (or type(type).isBucketType()) before calling get/bind.
  2. Fix the source column type to a bucketable type or choose a supported transform (truncate, identity) for that type.
  3. If handling an unknown type is expected, catch IllegalArgumentException and surface a clear spec-validation error.

Example fix

// before
Function<Integer, Integer> fn = Bucket.get(type, numBuckets).bind(type);
// after
Preconditions.checkArgument(Bucket.get(type).contains(type), "Type %s is not bucketable", type);
Function<Integer, Integer> fn = Bucket.get(type, numBuckets).bind(type);
Defensive patterns

Strategy: validation

Validate before calling

if (!Bucket.get(type).contains(type)) { throw new IllegalArgumentException("Cannot bucket by type: " + type); }

Type guard

boolean isBucketable(Type t) { return Bucket.get(t).contains(t); }

Try / catch

try { return Bucket.get(type, numBuckets).bind(type); } catch (IllegalArgumentException e) { throw new SchemaParseException("Unsupported bucket source type: " + type, e); }

Prevention

When it happens

Trigger: Calling Bucket.get(type, numBuckets) with an unsupported Type (e.g. boolean, map, list, struct), or binding a bucket transform to an incompatible type via Bucket.bind(type) when canTransform was bypassed.

Common situations: Constructing partition specs programmatically with a bucket transform on a non-bucketable column type; custom catalog/visitor code building transforms from parsed specs with wrong type mapping; version changes adding new bucketable types (e.g. TIMESTAMP_NANO) not handled by downstream code.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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