apache/iceberg · error · IllegalArgumentException

Unknown logical type: ${logicalType}

Error message

Unknown logical type: ${logicalType}

What it means

SparkPlannedAvroReader maps Avro logical types (date, timestamp-millis, decimal, uuid, etc.) to value readers. An Avro logical type name outside the recognized set triggers IllegalArgumentException('Unknown logical type: ...').

Source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/data/SparkPlannedAvroReader.java:162

          case "timestamp-millis":
            // adjust to microseconds
            ValueReader<Long> longs = ValueReaders.longs();
            return (ValueReader<Long>) (decoder, ignored) -> longs.read(decoder, null) * 1000L;

          case "timestamp-micros":
            // Spark uses the same representation
            return ValueReaders.longs();

          case "decimal":
            return SparkValueReaders.decimal(
                ValueReaders.decimalBytesReader(primitive),
                ((LogicalTypes.Decimal) logicalType).getScale());

          case "uuid":
            return SparkValueReaders.uuids();

          default:
            throw new IllegalArgumentException("Unknown logical type: " + logicalType);
        }
      }

      switch (primitive.getType()) {
        case NULL:
          return ValueReaders.nulls();
        case BOOLEAN:
          return ValueReaders.booleans();
        case INT:
          if (partner != null && partner.typeId() == Type.TypeID.LONG) {
            return ValueReaders.intsAsLongs();
          }
          return ValueReaders.ints();
        case LONG:
          return ValueReaders.longs();
        case FLOAT:
          if (partner != null && partner.typeId() == Type.TypeID.DOUBLE) {
            return ValueReaders.floatsAsDoubles();

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Upgrade Iceberg so the reader recognizes the logical type.
  2. Remove or convert the custom logical-typed field before writing files.
  3. Strip or change the logical type annotation in the producing Avro schema.

Example fix

// before
{"name":"f","type":"long","logicalType":"custom-thing"}
// after
{"name":"f","type":"long"}
Defensive patterns

Strategy: validation

Validate before calling

Schema avroSchema = new Schema.Parser().parse(schemaJson);
for (Field f : avroSchema.getFields()) {
  LogicalType lt = f.schema().getLogicalType();
  if (lt != null && !Set.of("date","timestamp-millis","timestamp-micros","decimal","uuid","time-millis","time-micros").contains(lt.getName()))
    throw new IllegalStateException("unknown logical type: " + lt.getName());
}

Try / catch

try {
  reader = SparkPlannedAvroReader.create(avroSchema);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Unknown logical type")) {
    // strip/convert the custom logical type and retry
  }
}

Prevention

When it happens

Trigger: Reading an Avro-backed Iceberg file whose schema declares a logical type the reader doesn't know (custom or newer logical type names).

Common situations: Avro files produced by external tools with custom logical types; reading files written by newer Iceberg/Avro versions with logical types unknown to the runtime's reader.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/ff3112bd88a26a23. Report an issue: GitHub.