apache/iceberg · error · IllegalStateException

Unknown type for int field. Type name: " +…

Error message

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

What it means

StructRowData.getInt converts the Object stored in the wrapped Iceberg StructLike at pos into a Flink INT. It accepts Integer, LocalDate (Date field, converted to epoch day) and LocalTime (Time field, converted to millisecond-of-day); any other runtime type means the struct holds a value inconsistent with an int-typed field and IllegalStateException is thrown with the actual class name.

Solutions

  1. Verify the Iceberg schema passed to StructRowData matches the actual types of the underlying StructLike data; re-align field positions/types.
  2. Check what class the error names — the message prints the actual stored type; fix the writer/reader so an int field stores Integer, LocalDate or LocalTime.
  3. If reading files written by another engine/version, rewrite or re-read with the schema the files were written with.
  4. Wrap getInt with a pre-check: struct.get(pos, Object.class) type inspection before calling, converting unsupported types explicitly.

Example fix

// before
int v = structRowData.getInt(pos); // IllegalStateException for unexpected type

// after
Object raw = struct.get(pos, Object.class);
int v;
if (raw instanceof Integer i) {
  v = i;
} else if (raw instanceof Long l) {
  v = Math.toIntExact(l);
} else if (raw instanceof String s) {
  v = Integer.parseInt(s);
} else {
  v = structRowData.getInt(pos);
}
Defensive patterns

Strategy: validation

Validate before calling

Object raw = struct.get(pos, Object.class);
Preconditions.checkArgument(
    raw == null || raw instanceof Integer || raw instanceof LocalDate || raw instanceof LocalTime,
    "int field holds unexpected type: %s", raw == null ? "null" : raw.getClass());

Type guard

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

Try / catch

try {
  int v = structRowData.getInt(pos);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Unknown type for int field")) {
    log.error("Schema mismatch on int column at pos {}", pos, e);
    throw new SchemaMismatchException(e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Reading a projected/int column via StructRowData.getInt(pos) when the underlying StructLike stores something other than Integer/LocalDate/LocalTime — e.g. a Long or String written by a custom writer or an incompatible schema at read time.

Common situations: Schema drift between the table schema used to write the data and the schema supplied when reading; custom StructLike implementations (e.g. wrapped GenericRecord or Row) storing boxed types outside the expected set; reading Date/Time columns whose backing representation changed across Iceberg versions.

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

Appendix: source

Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/data/StructRowData.java:130

  }

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

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

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

  @Override
  public long getLong(int pos) {
    Object longVal = struct.get(pos, 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 if (longVal instanceof LocalTime) {
      return ((LocalTime) longVal).toNanoOfDay();
    } else if (longVal instanceof LocalDateTime) {
      return Duration.between(Instant.EPOCH, ((LocalDateTime) longVal).atOffset(ZoneOffset.UTC))

View on GitHub (pinned to 86d9c8fc54)