apache/iceberg · error · IllegalArgumentException
Unsupported logical type:
Error message
Unsupported logical type:
What it means
SparkAvroWriter.primitive maps Avro logical types to Iceberg value writers. Only date, timestamp-millis/micros, decimal, and uuid logical types are recognized; anything else hits the default branch. This IllegalArgumentException reports that the Avro schema contains a logical type the Spark-to-Iceberg writer cannot handle.
Source
Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/data/SparkAvroWriter.java:137
if (logicalType != null) {
switch (logicalType.getName()) {
case "date":
// Spark uses the same representation
return ValueWriters.ints();
case "timestamp-micros":
// Spark uses the same representation
return ValueWriters.longs();
case "decimal":
LogicalTypes.Decimal decimal = (LogicalTypes.Decimal) logicalType;
return SparkValueWriters.decimal(decimal.getPrecision(), decimal.getScale());
case "uuid":
return SparkValueWriters.uuids();
default:
throw new IllegalArgumentException("Unsupported logical type: " + logicalType);
}
}
switch (primitive.getType()) {
case NULL:
return ValueWriters.nulls();
case BOOLEAN:
return ValueWriters.booleans();
case INT:
if (type instanceof ByteType) {
return ValueWriters.tinyints();
} else if (type instanceof ShortType) {
return ValueWriters.shorts();
}
return ValueWriters.ints();
case LONG:
return ValueWriters.longs();
case FLOAT:View on GitHub (pinned to 86d9c8fc54)
Solutions
- Remove or normalize the unsupported logical type from the Avro schema (write as underlying primitive).
- Convert time-millis/time-micros fields to timestamp-micros or plain int/long before writing.
- Upgrade Iceberg if a newer release supports the logical type.
- If writing via a different library, use a writer that supports the logical type.
Example fix
// before (Avro schema)
{"name":"t","type":"int","logicalType":"time-millis"}
// after
{"name":"t","type":"long","logicalType":"timestamp-micros"} Defensive patterns
Strategy: validation
Validate before calling
// Inspect the Avro schema's logical types before writing
for (org.apache.avro.Schema.Field f : avroSchema.getFields()) {
org.apache.avro.LogicalType lt = f.schema().getLogicalType();
if (lt != null && !Set.of("date", "timestamp-millis", "timestamp-micros", "decimal", "uuid").contains(lt.getName())) {
throw new IllegalStateException("Unsupported logical type: " + lt.getName());
}
} Type guard
static boolean isSupportedLogicalType(org.apache.avro.Schema s) {
org.apache.avro.LogicalType lt = s.getLogicalType();
return lt == null || Set.of("date", "timestamp-millis", "timestamp-micros", "decimal", "uuid").contains(lt.getName());
} Prevention
- Normalize Avro schemas to supported logical types before writing
- Check source tool output schemas for time-millis/time-micros
- Prefer plain primitives when the logical type is unused
When it happens
Trigger: Writing Spark InternalRows to an Avro container whose schema declares a logical type other than date, timestamp-millis, timestamp-micros, decimal, or uuid (e.g. time-millis, time-micros, duration, or a custom logicalType).
Common situations: Third-party tools emit Avro schemas with time-millis/time-micros or vendor-specific logical types; attempts to write such data through Iceberg's SparkAvroWriter path fail.
Related errors
- Unknown logical type:
- Unsupported logical type: %s
- Unsupported type:
- Unknown logical type: ${logicalType}
- Unsupported logical type:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/8a3754dd8c4995d3.
Report an issue: GitHub.