apache/iceberg · error · UnsupportedOperationException
Unsupported type: interval
Error message
Unsupported type: interval
What it means
StructInternalRow wraps Iceberg InternalRow data into a Spark InternalRow. CalendarInterval (Spark's INTERVAL type) is not supported by Iceberg's type system, so getInterval unconditionally throws UnsupportedOperationException. Iceberg has no interval type, so no value can ever be provided here.
Solutions
- Remove interval-typed fields from the query projection over the Iceberg table
- Compute intervals in Spark after reading, from supported Iceberg types (long/int), rather than expecting an interval column
- Upgrade Iceberg: newer versions may add support for interval via Spark compatibility layers
- If this is your own wrapping code, use Spark's GenericInternalRow for rows containing intervals instead of StructInternalRow
Example fix
// before row.getInterval(0); // throws // after long months = row.getLong(0); // store interval components in supported numeric columns java.time.Period p = java.time.Period.ofMonths((int) months);
Defensive patterns
Strategy: validation
Validate before calling
if (schema.fields().stream().anyMatch(f -> f.dataType() instanceof CalendarIntervalType)) {
throw new IllegalArgumentException("Iceberg StructInternalRow does not support interval columns; project them out");
} Type guard
static boolean hasIntervalField(StructType schema) {
return java.util.Arrays.stream(schema.fields())
.anyMatch(f -> f.dataType() instanceof CalendarIntervalType);
} Prevention
- Keep interval math in Spark post-read, not in the Iceberg-backed schema
- Validate projected schemas exclude CalendarInterval before scanning Iceberg tables
When it happens
Trigger: A Spark job reads an Iceberg table where the projected schema causes Spark to call getInterval on the wrapped row — e.g. schema evolution/type inference paths or a query referencing an interval-typed expression backed by this row adapter.
Common situations: Queries combining Iceberg scans with Spark INTERVAL columns, or custom code casting StructInternalRow rows to a schema containing CalendarInterval fields.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unsupported type: interval
- Unsupported type: interval
- Unsupported type: interval
- Cannot convert type to SQL
- Cannot convert unsupported type to Spark
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/89c4f2bf93271e50.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java:208
}
private byte[] getBinaryInternal(int ordinal) {
Object bytes = struct.get(ordinal, Object.class);
// should only be either ByteBuffer or byte[]
if (bytes instanceof ByteBuffer) {
return ByteBuffers.toByteArray((ByteBuffer) bytes);
} else if (bytes instanceof byte[]) {
return (byte[]) bytes;
} else {
throw new IllegalStateException(
"Unknown type for binary field. Type name: " + bytes.getClass().getName());
}
}
@Override
public CalendarInterval getInterval(int ordinal) {
throw new UnsupportedOperationException("Unsupported type: interval");
}
@Override
public InternalRow getStruct(int ordinal, int numFields) {
return isNullAt(ordinal) ? null : getStructInternal(ordinal);
}
private InternalRow getStructInternal(int ordinal) {
return new StructInternalRow(
type.fields().get(ordinal).type().asStructType(), struct.get(ordinal, StructLike.class));
}
@Override
public ArrayData getArray(int ordinal) {
return isNullAt(ordinal) ? null : getArrayInternal(ordinal);
}
private ArrayData getArrayInternal(int ordinal) {View on GitHub (pinned to 86d9c8fc54)