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 stored field value to a Spark long, accepting Long, OffsetDateTime (Timestamptz), LocalDateTime-backed values, or LocalDate (Date). Any other stored type triggers an IllegalStateException naming the actual class.

Source

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

      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. Read the field with getInt when the stored value is an Integer, or convert the stored type to Long before reading
  2. Align the Iceberg schema with the physical data and rewrite metadata/data if types drifted
  3. Verify which Java representation the column actually stores (Long, OffsetDateTime, LocalDate) and use the matching getter

Example fix

// before
long v = structRow.getLong(ordinal); // stored Integer
// after
Object val = ((StructLike) structRow.getStruct(ordinal, null)).get(ordinal, null);
long v = val instanceof Integer ? (Integer) val : structRow.getLong(ordinal);
Defensive patterns

Strategy: type-guard

Validate before calling

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

Type guard

boolean isLongField(Object v) {
  return v instanceof Long || v instanceof java.time.OffsetDateTime || v instanceof java.time.LocalDateTime || v instanceof java.time.LocalDate;
}

Try / catch

try {
  return row.getLong(ordinal);
} catch (IllegalStateException e) {
  // handle Integer-stored values via getInt or explicit conversion
}

Prevention

When it happens

Trigger: Calling getLong(ordinal) when the struct field holds an unexpected object type, e.g. an Integer stored for a Long column, or a type drifted from the declared Iceberg schema.

Common situations: Schema evolution/type promotion (int -> long) where old data or views still supply Integer; timestamp representation mismatches between table spec versions; custom readers storing unexpected Java classes.

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