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 a StructLike value to a Spark long, accepting Long, OffsetDateTime (timestamptz -> microseconds since epoch), LocalDate (date -> epoch day), Timestamp, and LocalDateTime. Any other object type throws IllegalStateException with the actual Java class name, meaning the physical value doesn't match the declared long-backed Iceberg type.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java:147

      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. Verify the Iceberg column type (long vs timestamp vs timestamptz) matches what the reader actually stores
  2. Use the class name in the message to find the code path writing the unexpected object
  3. Fix the producer to store Long, OffsetDateTime, Timestamp, LocalDateTime, or LocalDate
  4. Convert the value manually via get(ordinal, null) if you control the call site

Example fix

// before
long v = row.getLong(ordinal); // value is Integer
// after
Object raw = row.get(ordinal, null);
long v = raw instanceof Integer ? ((Integer) raw).longValue() : row.getLong(ordinal);
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = row.get(ordinal, null);
if (!(v instanceof Long || v instanceof OffsetDateTime || v instanceof LocalDate
    || v instanceof Timestamp || v instanceof LocalDateTime)) {
  throw new IllegalStateException("Unexpected long-field value: " + v.getClass());
}

Type guard

boolean isLongCompatible(Object v) { return v instanceof Long || v instanceof OffsetDateTime
    || v instanceof LocalDate || v instanceof Timestamp || v instanceof LocalDateTime; }

Try / catch

try {
  return row.getLong(ordinal);
} catch (IllegalStateException e) {
  throw new IllegalStateException("Long/timestamp field held unexpected Java type", e);
}

Prevention

When it happens

Trigger: A column declared as long/timestamp/timestamptz/date whose stored StructLike value is none of the expected types (e.g. Integer, BigDecimal, or a wrongly-typed object from a custom producer).

Common situations: Custom record producers putting wrong types in StructLike; schema evolution mismatch; mis-declared partition/type mapping between Iceberg and Spark; bugs in timestamp conversion paths.

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