apache/iceberg · error · IllegalArgumentException

Avro does not support TIMESTAMP type with precision: ${preci

Error message

Avro does not support TIMESTAMP type with precision: ${precision}, it only supports precision less than 3.

What it means

When converting a Flink TIMESTAMP (TIMESTAMP_WITHOUT_TIME_ZONE) LogicalType to an Avro schema with legacyTimestampMapping=true, only precision <= 3 is representable (timestampMillis). Higher precision has no legacy Avro logical type, so IllegalArgumentException stating Avro supports only precision less than 3 is thrown.

Source

Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/formats/avro/typeutils/AvroSchemaConverter.java:488

        return nullable ? nullableSchema(doubleSchema) : doubleSchema;
      case CHAR:
      case VARCHAR:
        Schema str = SchemaBuilder.builder().stringType();
        return nullable ? nullableSchema(str) : str;
      case BINARY:
      case VARBINARY:
        Schema binary = SchemaBuilder.builder().bytesType();
        return nullable ? nullableSchema(binary) : binary;
      case TIMESTAMP_WITHOUT_TIME_ZONE:
        // use long to represents Timestamp
        final TimestampType timestampType = (TimestampType) logicalType;
        precision = timestampType.getPrecision();
        org.apache.avro.LogicalType avroLogicalType;
        if (legacyTimestampMapping) {
          if (precision <= 3) {
            avroLogicalType = LogicalTypes.timestampMillis();
          } else {
            throw new IllegalArgumentException(
                "Avro does not support TIMESTAMP type "
                    + "with precision: "
                    + precision
                    + ", it only supports precision less than 3.");
          }
        } else {
          if (precision <= 3) {
            avroLogicalType = LogicalTypes.localTimestampMillis();
          } else if (precision <= 6) {
            avroLogicalType = LogicalTypes.localTimestampMicros();
          } else {
            throw new IllegalArgumentException(
                "Avro does not support LOCAL TIMESTAMP type "
                    + "with precision: "
                    + precision
                    + ", it only supports precision less than 6.");
          }
        }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Pass legacyTimestampMapping=false to convertToSchema so precision <= 6 maps to localTimestampMicros/timestampMicros variants.
  2. Change the column to TIMESTAMP(3) or lower in the Flink DDL so it fits timestampMillis.
  3. Cast the column in SQL: CAST(ts AS TIMESTAMP(3)) before writing to Avro.
  4. Migrate downstream consumers to non-legacy (logical-type) Avro timestamps, then disable legacy mapping.

Example fix

// before
Schema s = AvroSchemaConverter.convertToSchema(new TimestampType(6), true); // throws
// after
Schema s = AvroSchemaConverter.convertToSchema(new TimestampType(6), false); // micros logical type
// or lower the precision: new TimestampType(3)
Defensive patterns

Strategy: validation

Validate before calling

TimestampType ts = (TimestampType) logicalType;
if (legacyMapping && ts.getPrecision() > 3) {
  throw new IllegalStateException("TIMESTAMP(" + ts.getPrecision() + ") needs legacyTimestampMapping=false or precision <= 3");
}

Try / catch

try {
  Schema s = AvroSchemaConverter.convertToSchema(timestampType, legacyMapping);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("it only supports precision less than 3")) {
    s = AvroSchemaConverter.convertToSchema(new TimestampType(3), legacyMapping); // degrade precision
  } else throw e;
}

Prevention

When it happens

Trigger: AvroSchemaConverter.convertToSchema(LogicalType, boolean) — also reached recursively via fieldBuilder for nested fields — with a TimestampType whose precision > 3 while legacyTimestampMapping is true (e.g. TIMESTAMP(6), the Flink default).

Common situations: Flink SQL DDL declaring TIMESTAMP(6)/(9) but the Avro writer configured with legacy timestamp mapping; older Flink/Iceberg configs setting legacy mapping for backward compatibility with pre-1.10 consumers.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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