apache/iceberg · error · java.lang.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

StructRowData.getLong(pos) converts the field at pos to a Flink BIGINT, accepting Long, Date, LocalDate, LocalTime, and LocalDateTime values (converted to epoch units). If the underlying object is any other class, it throws IllegalStateException with the class name. The stored value doesn't match a long-representable Iceberg type.

Source

Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/data/StructRowData.java:152

  @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))
              .toNanos()
          / 1000;
    } else {
      throw new IllegalStateException(
          "Unknown type for long field. Type name: " + longVal.getClass().getName());
    }
  }

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

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

  @Override
  public StringData getString(int pos) {
    return isNullAt(pos) ? null : getStringDataInternal(pos);
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Verify the Iceberg schema type for the column is long/date/time/timestamp
  2. Fix the upstream producer so it stores Long or java.time values
  3. Use the matching accessor (getString, getTimestamp, getBigDecimal-equivalent) for the real type

Example fix

// before
long v = structRowData.getLong(pos); // stored value is BigDecimal
// after
BigDecimal d = (BigDecimal) structRowData.getValue(pos);
long v = d.unscaledValue().longValueExact();
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = structRowData.getValue(pos);
if (!(v instanceof Long || v instanceof LocalDate || v instanceof LocalTime || v instanceof LocalDateTime || v instanceof java.util.Date)) {
  throw new IllegalArgumentException("getLong unsupported value at " + pos + ": " + (v == null ? "null" : v.getClass()));
}

Type guard

boolean longReadable(Object v) { return v instanceof Long || v instanceof LocalDate || v instanceof LocalTime || v instanceof LocalDateTime || v instanceof java.util.Date; }

Try / catch

try { long x = row.getLong(pos); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Unknown type for long field")) { /* use matching accessor */ } else throw e; }

Prevention

When it happens

Trigger: Calling getLong on a field whose stored value is not Long/Date/LocalDate/LocalTime/LocalDateTime — e.g. a String, BigDecimal, or TimestampData where the schema expected long/timestamp.

Common situations: Schema/data mismatch from a custom source or connector feeding wrong object types; wrong accessor chosen for a string or decimal column.

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