apache/iceberg · error · IllegalStateException

Unknown type for long field. Type name: " + longVal.getClass

Error message

Unknown type for long field. Type name: " + longVal.getClass().getName()

What it means

StructInternalRow.getLong converts the underlying Iceberg struct field to a Spark BIGINT/TIMESTAMP long. It supports Long, OffsetDateTime (timestamp), Duration-equivalent nanos, and LocalDate (date-to-epoch-day); any other runtime type triggers this IllegalStateException naming the actual class.

Source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java:153

      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());
    }
  }

  @Override
  public float getFloat(int ordinal) {
    return struct.get(ordinal, Float.class);
  }

  @Override
  public double getDouble(int ordinal) {
    return struct.get(ordinal, Double.class);
  }

  @Override
  public Decimal getDecimal(int ordinal, int precision, int scale) {
    return isNullAt(ordinal) ? null : getDecimalInternal(ordinal);
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Align the expected Spark schema with the table's actual field types (e.g. read a Timestamp column with getLong only if the producer yields OffsetDateTime)
  2. Fix the producer/row wrapper to store the type Iceberg's conversion expects (Long for long, OffsetDateTime for timestamp, LocalDate for date)
  3. Print/inspect the class name from the message to identify what is actually stored and adapt accordingly
  4. Upgrade Iceberg if your version's timestamp Java mapping differs from the reader's expectations

Example fix

// before
row.getLong(tsOrdinal); // stored LocalTime -> IllegalStateException
// after
Object v = row.get(tsOrdinal, sparkType); // confirm stored class first
long nanos = v instanceof OffsetDateTime
    ? Duration.between(Instant.EPOCH, (OffsetDateTime) v).toNanos() / 1000
    : (Long) v;
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = struct.get(pos, javaClass);
if (!(v instanceof Long) && !(v instanceof OffsetDateTime) && !(v instanceof LocalDate)) {
  throw new IllegalStateException("expected Long/OffsetDateTime/LocalDate for long field, got " + v.getClass());
}

Type guard

boolean isLongBacked(Object v) {
  return v instanceof Long || v instanceof OffsetDateTime || v instanceof LocalDate;
}

Try / catch

try { long l = row.getLong(ordinal); } catch (IllegalStateException e) { /* read the class name from the message and correct schema/producer */ }

Prevention

When it happens

Trigger: Expected schema says LongType/TimestampType at the ordinal but the struct holds a different Java object (e.g. Integer, BigDecimal, LocalTime) — a mismatch between the declared read schema and the actual stored Java classes.

Common situations: Timestamp vs timestamp_ntz vs time mapping confusion; wrong schema passed to Spark scan; Iceberg version differences in the Java class chosen for timestamp types (LocalDateTime vs OffsetDateTime 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/dcab927504c5d82e. Report an issue: GitHub.