apache/iceberg · error · IllegalArgumentException

Unsupported logical type:

Error message

Unsupported logical type: 

What it means

DataWriter maps Avro primitive schemas with logical types (decimal, uuid) to Iceberg ValueWriters; when it sees a logical type name it does not handle, this IllegalArgumentException is thrown listing nothing extra — just the logicalType string. Primitive types without logical types fall through to the normal switch below.

Source

Thrown at core/src/main/java/org/apache/iceberg/data/avro/DataWriter.java:141

              return GenericWriters.timestamptz();
            }
            return GenericWriters.timestamps();

          case "timestamp-nanos":
            if (AvroSchemaUtil.isTimestamptz(primitive)) {
              return GenericWriters.timestamptzNanos();
            }
            return GenericWriters.timestampNanos();

          case "decimal":
            LogicalTypes.Decimal decimal = (LogicalTypes.Decimal) logicalType;
            return ValueWriters.decimal(decimal.getPrecision(), decimal.getScale());

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

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

      switch (primitive.getType()) {
        case NULL:
          return ValueWriters.nulls();
        case BOOLEAN:
          return ValueWriters.booleans();
        case INT:
          return ValueWriters.ints();
        case LONG:
          return ValueWriters.longs();
        case FLOAT:
          return ValueWriters.floats();
        case DOUBLE:
          return ValueWriters.doubles();
        case STRING:
          return ValueWriters.strings();

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Convert the field to a supported type (decimal or uuid) before writing
  2. Handle unsupported logical types upstream by stripping the logical type or converting values to an Iceberg-supported primitive
  3. Extend the writer with a mapping if the logical type maps naturally to an Iceberg type (e.g. timestamp)

Example fix

// before
// schema: {"type":"int","logicalType":"time-millis"} passed to DataWriter
// after
// convert value to the target Iceberg type first, e.g. TimeType written via TimeMicrosWriter
long micros = TimeUnit.MILLISECONDS.toMicros(millisOfDay);
Defensive patterns

Strategy: validation

Validate before calling

LogicalType lt = schema.getLogicalType();
String name = lt != null ? lt.getName() : null;
if (name != null && !"decimal".equals(name) && !"uuid".equals(name)) throw new IllegalStateException("unsupported logical type: " + name);

Type guard

boolean supportedLogicalType(Schema s) { Object lt = s.getLogicalType(); return lt == null || lt instanceof LogicalTypes.Decimal || "uuid".equals(lt.getName()); }

Try / catch

try { DataWriter.write(encoder, schema, value); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Unsupported logical type")) { /* convert upstream */ } else throw e; }

Prevention

When it happens

Trigger: Writing Avro data with a primitive schema carrying a logical type other than decimal or uuid (e.g. time-millis, timestamp-micros, or a custom logical type).

Common situations: Foreign Avro files with timestamp/timedelta logical types being written through the Iceberg generic writer; custom Avro logical types from other systems.

Related errors


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