apache/iceberg · error · IllegalStateException

Unknown type for int field. Type name: + integer.getClass().

Error message

Unknown type for int field. Type name: + integer.getClass().getName()

What it means

StructInternalRow.getInt converts the stored field value to a Spark int, accepting Integer or LocalDate (Iceberg Date). If the stored object is neither (a data/spec mismatch between the Iceberg type and what was stored), it throws IllegalStateException naming the actual class.

Source

Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java:135

  public byte getByte(int ordinal) {
    return (byte) (int) struct.get(ordinal, Integer.class);
  }

  @Override
  public short getShort(int ordinal) {
    return (short) (int) struct.get(ordinal, Integer.class);
  }

  @Override
  public int getInt(int ordinal) {
    Object integer = struct.get(ordinal, Object.class);

    if (integer instanceof Integer) {
      return (int) integer;
    } else if (integer instanceof LocalDate) {
      return (int) ((LocalDate) integer).toEpochDay();
    } else {
      throw new IllegalStateException(
          "Unknown type for int field. Type name: " + integer.getClass().getName());
    }
  }

  @Override
  public long getLong(int ordinal) {
    Object longVal = struct.get(ordinal, Object.class);

    if (longVal instanceof Long) {
      return (long) longVal;
    } else if (longVal instanceof OffsetDateTime) {
      return Duration.between(Instant.EPOCH, (OffsetDateTime) longVal).toNanos() / 1000;
    } else if (longVal instanceof LocalDate) {
      return ((LocalDate) longVal).toEpochDay();
    } else {
      throw new IllegalStateException(
          "Unknown type for long field. Type name: " + longVal.getClass().getName());
    }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check the stored type named in the message and read the field with the matching getter (getLong for long-backed types)
  2. Align the requested Spark type with the Iceberg schema (Date -> int, Timestamp -> long)
  3. Rewrite data or refresh metadata if the physical type drifted from the declared schema

Example fix

// before
int v = structRow.getInt(dateOrdinal); // stores OffsetDateTime
// after
long epochDayMicros = structRow.getLong(dateOrdinal); // match stored representation
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = structLike.get(ordinal, null);
if (!(v instanceof Integer || v instanceof LocalDate)) {
  throw new IllegalArgumentException("Field " + ordinal + " is not int-compatible: " + v.getClass());
}

Type guard

boolean isIntField(Object v) { return v instanceof Integer || v instanceof LocalDate; }

Try / catch

try {
  return row.getInt(ordinal);
} catch (IllegalStateException e) {
  // fall back to getLong/conversion based on the stored type
}

Prevention

When it happens

Trigger: Calling getInt(ordinal) on a StructInternalRow whose underlying struct field holds an object that is not Integer or LocalDate, e.g. a long-backed timestamp stored where an int-typed (Date) column was expected.

Common situations: Schema evolution changing a column type without rewriting data; reading Date data where the struct actually stores a different Java representation; type-promotion mismatches between table schema and read schema.

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/b01b5e112e161887. Report an issue: GitHub.