apache/iceberg · error · IllegalStateException
Unknown type for long field. Type name:
Error message
Unknown type for long field. Type name:
What it means
StructInternalRow.getLong converts the underlying value of a long/timestamp field to a Java long, accepting Long, OffsetDateTime (timestamptz), and LocalDate (date-as-days). Any other runtime type throws this IllegalStateException with the actual class name.
Source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java:156
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
- Ensure the accessor matches the declared Iceberg type (getLong only for long/timestamptz/date semantics)
- Reconcile schema drift: refresh the table schema and Spark conversion so field types match the data
- Inspect the type name in the message and fix the producer writing that wrong type
Example fix
// before row.getLong(timeFieldOrdinal); // throws: value is LocalTime // after // time fields must be routed to getTime or converted upstream long nanos = ((LocalTime) value).toNanoOfDay();
Defensive patterns
Strategy: validation
Validate before calling
// Java
Object v = struct.getField(ordinal);
if (!(v instanceof Long) && !(v instanceof OffsetDateTime) && !(v instanceof LocalDate)) {
throw new IllegalStateException("Expected Long/OffsetDateTime/LocalDate, got " + v.getClass());
} Type guard
boolean isValidLongFieldValue(Object v) {
return v instanceof Long || v instanceof OffsetDateTime || v instanceof LocalDate;
} Try / catch
try {
long l = row.getLong(ordinal);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Unknown type for long field")) {
// use the correct accessor for the field's declared type
}
throw e;
} Prevention
- Use getLong only for long/timestamptz/date fields
- Route time fields to the proper accessor (getTime) or convert upstream
- Refresh cached schemas after table evolution
When it happens
Trigger: Reading a long/Timestamp/Timestamptz field whose stored value is none of Long, OffsetDateTime, or LocalDate — e.g. LocalTime for a time field read through the wrong accessor or a String/BigDecimal in the row.
Common situations: Schema drift between the Iceberg schema and the Spark read schema, custom StructLike values with unexpected boxed types, or microsecond/nanosecond conversion code invoked on fields of the wrong declared type.
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
- Unsupported type: ${primitive}
- Unknown type for int field. Type name:
- Invalid iceberg type %s corresponding to ORC type %s
- Unsupported primitive type for decimal: <type>
- Table does not implement %s: %s (%s)
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/89b2d8cabc046842.
Report an issue: GitHub.