pentaho/pentaho-kettle · error · IllegalArgumentException

Unsupported data type for timestamp conversion:

Error message

Unsupported data type for timestamp conversion: 

What it means

AvroTimestampHandler.toTimestamp converts a raw Avro long into a java.sql.Timestamp, supporting only the TIMESTAMP_MILLIS, TIMESTAMP_MICROS and TIMESTAMP_NANOS logical types. Any other AvroSpec.DataType falls through to the switch default and throws this IllegalArgumentException.

Solutions

  1. Ensure the Avro field's schema declares logicalType timestamp-millis/micros/nanos before calling toTimestamp.
  2. Route non-timestamp types (DATE, TIME_*) to the appropriate converter instead of toTimestamp.
  3. For plain longs, decide the intended unit yourself and use toTimestampMillis/Micros/Nanos explicitly.
  4. If a new logical type must be supported, add a case to the switch in AvroTimestampHandler.

Example fix

// before
Timestamp ts = AvroTimestampHandler.toTimestamp(value, AvroSpec.DataType.DATE); // throws
// after
if (dataType == AvroSpec.DataType.TIMESTAMP_MILLIS
    || dataType == AvroSpec.DataType.TIMESTAMP_MICROS
    || dataType == AvroSpec.DataType.TIMESTAMP_NANOS) {
  Timestamp ts = AvroTimestampHandler.toTimestamp(value, dataType);
} else {
  // handle DATE with a date-specific conversion
}
Defensive patterns

Strategy: type-guard

Validate before calling

java.util.Set<AvroSpec.DataType> OK = java.util.Set.of(
  AvroSpec.DataType.TIMESTAMP_MILLIS, AvroSpec.DataType.TIMESTAMP_MICROS, AvroSpec.DataType.TIMESTAMP_NANOS);
if (!OK.contains(dataType)) throw new IllegalArgumentException("Not a timestamp logical type: " + dataType);

Type guard

static boolean isTimestampType(AvroSpec.DataType t) {
  return t == AvroSpec.DataType.TIMESTAMP_MILLIS
      || t == AvroSpec.DataType.TIMESTAMP_MICROS
      || t == AvroSpec.DataType.TIMESTAMP_NANOS;
}

Try / catch

try {
  Timestamp ts = AvroTimestampHandler.toTimestamp(avroData, dataType);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Unsupported data type")) {
    logger.error("Field logical type is " + dataType + ", not a timestamp type");
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling toTimestamp(long, dataType) with a dataType that is not one of the three timestamp logical types — e.g. DATE, TIME_MILLIS, or a plain INT/LONG type with no timestamp logical type.

Common situations: An Avro field declared as plain long (no logicalType) is passed to timestamp conversion; a DATE logical type is mistakenly routed through toTimestamp instead of a date converter; a new Avro logical type added upstream but not handled here.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/d00c4dd774f3c509. Report an issue: GitHub.

Appendix: source

Thrown at plugins/avro-format/core/src/main/java/org/pentaho/di/trans/steps/avro/AvroTimestampHandler.java:36

/**
 * Utility class for handling conversions between Avro timestamp formats and Java `Timestamp`.
 */
public class AvroTimestampHandler {

  /**
   * Converts Avro timestamp data to a Java `Timestamp` based on the specified Avro data type.
   *
   * @param avroData The timestamp data in Avro format.
   * @param dataType The Avro data type (e.g., TIMESTAMP_MILLIS, TIMESTAMP_MICROS, TIMESTAMP_NANOS).
   * @return The corresponding Java `Timestamp` having milli/micro/nanosecond precision depending on type.
   * @throws IllegalArgumentException if the data type is unsupported.
   */
  public static Timestamp toTimestamp( long avroData, AvroSpec.DataType dataType ) {
    return switch ( dataType ) {
      case TIMESTAMP_MILLIS -> toTimestampMillis( avroData );
      case TIMESTAMP_MICROS -> toTimestampMicros( avroData );
      case TIMESTAMP_NANOS -> toTimestampNanos( avroData );
      default -> throw new IllegalArgumentException(
        "Unsupported data type for timestamp conversion: " + dataType.name() );
    };
  }

  /**
   * Converts a timestamp in milliseconds to a Java `Timestamp`.
   * <p>
   * Calculation: Direct conversion - milliseconds since epoch to Timestamp constructor.
   *
   * @param millis The timestamp in milliseconds.
   * @return The corresponding Java `Timestamp` having millisecond precision.
   */
  private static Timestamp toTimestampMillis( long millis ) {
    return new Timestamp( millis );
  }

  /**
   * Converts a timestamp in microseconds to a Java `Timestamp`.

View on GitHub (pinned to f3058517a1)