apache/iceberg · error · IllegalArgumentException

Wrong class, expected %s, but was %s, for object: %s

Error message

Wrong class, expected %s, but was %s, for object: %s

What it means

PartitionData.get(pos) reads the value at a partition-struct position and casts it to the expected Java class. If the value is null it returns null; if the stored value's class is not an instance of javaClass (e.g. internal schema/field-type mismatch between expected partition type and actual data), it throws IllegalArgumentException. This signals an internal invariant violation: the partition field's type and the stored object disagree.

Source

Thrown at core/src/main/java/org/apache/iceberg/PartitionData.java:129

  }

  public void clear() {
    Arrays.fill(data, null);
  }

  @Override
  public int size() {
    return size;
  }

  @Override
  public <T> T get(int pos, Class<T> javaClass) {
    Object value = get(pos);
    if (value == null || javaClass.isInstance(value)) {
      return javaClass.cast(value);
    }

    throw new IllegalArgumentException(
        String.format(
            "Wrong class, expected %s, but was %s, for object: %s",
            javaClass.getName(), value.getClass().getName(), value));
  }

  @Override
  public Object get(int pos) {
    if (pos >= data.length) {
      return null;
    }

    if (data[pos] instanceof byte[]) {
      byte[] copied = Arrays.copyOf((byte[]) data[pos], ((byte[]) data[pos]).length);
      return ByteBuffer.wrap(copied);
    }

    return data[pos];
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Match the requested class to the partition field's Iceberg type: Integer for int/date, Long for long/timestamp, String, ByteBuffer for binary, etc.
  2. Use the correct PartitionSpec/schema when constructing or reading PartitionData — stale cached types cause mismatched positions.
  3. Wrap access with a check: Object v = partitionData.get(pos); assert javaClass.isInstance(v) before casting, to produce a clearer failure.
  4. For conversions, read as Object and convert explicitly (e.g. ((Number) v).longValue()) instead of assuming the class.

Example fix

// before
Long value = partitionData.get(0, Long.class); // field is actually int
// after
Integer value = partitionData.get(0, Integer.class);
Defensive patterns

Strategy: type-guard

Validate before calling

Types.NestedField field = spec.partitionType().fields().get(pos);
Class<?> expected = expectedJavaClass(field.type()); // map Iceberg type to Java class before calling get()

Type guard

Object raw = partitionData.get(pos);
T value = javaClass.isInstance(raw) ? javaClass.cast(raw) : null;

Try / catch

try {
  Long v = partitionData.get(pos, Long.class);
} catch (IllegalArgumentException e) {
  if (!e.getMessage().startsWith("Wrong class")) throw e;
  // re-read with correct type from spec.partitionType()
}

Prevention

When it happens

Trigger: Calling PartitionData.get(pos, Class) with a class that does not match the field's declared type at that position — e.g. get(0, Long.class) when the partition field is an int, or reading a PartitionData produced with a different PartitionSpec/schema than the one expected (spec evolution mismatch).

Common situations: Custom readers/writers or Spark/Flink projections assuming the wrong partition field type; partition spec evolution where cached partition type no longer matches stored data; test code constructing PartitionData with values of the wrong Java type (e.g. Integer vs Long).

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


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