{"record":{"id":"d00c4dd774f3c509","repo":"pentaho/pentaho-kettle","slug":"unsupported-data-type-for-timestamp-conversion","errorCode":null,"errorMessage":"Unsupported data type for timestamp conversion: ","messagePattern":"Unsupported data type for timestamp conversion: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"plugins/avro-format/core/src/main/java/org/pentaho/di/trans/steps/avro/AvroTimestampHandler.java","lineNumber":36,"sourceCode":"/**\n * Utility class for handling conversions between Avro timestamp formats and Java `Timestamp`.\n */\npublic class AvroTimestampHandler {\n\n  /**\n   * Converts Avro timestamp data to a Java `Timestamp` based on the specified Avro data type.\n   *\n   * @param avroData The timestamp data in Avro format.\n   * @param dataType The Avro data type (e.g., TIMESTAMP_MILLIS, TIMESTAMP_MICROS, TIMESTAMP_NANOS).\n   * @return The corresponding Java `Timestamp` having milli/micro/nanosecond precision depending on type.\n   * @throws IllegalArgumentException if the data type is unsupported.\n   */\n  public static Timestamp toTimestamp( long avroData, AvroSpec.DataType dataType ) {\n    return switch ( dataType ) {\n      case TIMESTAMP_MILLIS -> toTimestampMillis( avroData );\n      case TIMESTAMP_MICROS -> toTimestampMicros( avroData );\n      case TIMESTAMP_NANOS -> toTimestampNanos( avroData );\n      default -> throw new IllegalArgumentException(\n        \"Unsupported data type for timestamp conversion: \" + dataType.name() );\n    };\n  }\n\n  /**\n   * Converts a timestamp in milliseconds to a Java `Timestamp`.\n   * <p>\n   * Calculation: Direct conversion - milliseconds since epoch to Timestamp constructor.\n   *\n   * @param millis The timestamp in milliseconds.\n   * @return The corresponding Java `Timestamp` having millisecond precision.\n   */\n  private static Timestamp toTimestampMillis( long millis ) {\n    return new Timestamp( millis );\n  }\n\n  /**\n   * Converts a timestamp in microseconds to a Java `Timestamp`.","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/avro-format/core/src/main/java/org/pentaho/di/trans/steps/avro/AvroTimestampHandler.java#L18-L54","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the Avro field's schema declares logicalType timestamp-millis/micros/nanos before calling toTimestamp.","Route non-timestamp types (DATE, TIME_*) to the appropriate converter instead of toTimestamp.","For plain longs, decide the intended unit yourself and use toTimestampMillis/Micros/Nanos explicitly.","If a new logical type must be supported, add a case to the switch in AvroTimestampHandler."],"exampleFix":"// before\nTimestamp ts = AvroTimestampHandler.toTimestamp(value, AvroSpec.DataType.DATE); // throws\n// after\nif (dataType == AvroSpec.DataType.TIMESTAMP_MILLIS\n    || dataType == AvroSpec.DataType.TIMESTAMP_MICROS\n    || dataType == AvroSpec.DataType.TIMESTAMP_NANOS) {\n  Timestamp ts = AvroTimestampHandler.toTimestamp(value, dataType);\n} else {\n  // handle DATE with a date-specific conversion\n}","handlingStrategy":"type-guard","validationCode":"java.util.Set<AvroSpec.DataType> OK = java.util.Set.of(\n  AvroSpec.DataType.TIMESTAMP_MILLIS, AvroSpec.DataType.TIMESTAMP_MICROS, AvroSpec.DataType.TIMESTAMP_NANOS);\nif (!OK.contains(dataType)) throw new IllegalArgumentException(\"Not a timestamp logical type: \" + dataType);","typeGuard":"static boolean isTimestampType(AvroSpec.DataType t) {\n  return t == AvroSpec.DataType.TIMESTAMP_MILLIS\n      || t == AvroSpec.DataType.TIMESTAMP_MICROS\n      || t == AvroSpec.DataType.TIMESTAMP_NANOS;\n}","tryCatchPattern":"try {\n  Timestamp ts = AvroTimestampHandler.toTimestamp(avroData, dataType);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Unsupported data type\")) {\n    logger.error(\"Field logical type is \" + dataType + \", not a timestamp type\");\n  }\n  throw e;\n}","preventionTips":["Declare logicalType timestamp-millis/micros/nanos on Avro fields intended as timestamps.","Check the field's schema logical type before choosing a converter.","Handle DATE/TIME logical types with dedicated conversion code, not toTimestamp."],"tags":["avro","timestamp","type-mismatch","unsupported-type"],"backgroundTag":"unsupported-enum-value","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}