{"record":{"id":"33426f7f3254b25a","repo":"apache/seatunnel","slug":"unsupported-value-type-for-timestamp-tz-conversion","errorCode":null,"errorMessage":"Unsupported value type for TIMESTAMP_TZ conversion: ${value.getClass().getName()}, value='${value}', TiDB dataType=${dataType}","messagePattern":"Unsupported value type for TIMESTAMP_TZ conversion: (.+?), value='(.+?)', TiDB dataType=(.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-tidb/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/tidb/source/converter/DefaultDataConverter.java","lineNumber":299,"sourceCode":"            // LocalDateTime without explicit zone — treat as UTC wall-clock value.\n            return ((LocalDateTime) value).atOffset(ZoneOffset.UTC);\n        }\n        if (value instanceof String) {\n            // String representation from TiDB CDC — attempt ISO-8601 parse.\n            try {\n                return OffsetDateTime.parse((String) value);\n            } catch (java.time.format.DateTimeParseException e) {\n                throw new IllegalArgumentException(\n                        \"Unable to convert TIMESTAMP_TZ from String value: '\"\n                                + value\n                                + \"' for TiDB dataType: \"\n                                + dataType,\n                        e);\n            }\n        }\n        // Unknown type — fail fast with enough context for diagnosis instead of silently\n        // returning the raw value which would cause a ClassCastException downstream.\n        throw new IllegalArgumentException(\n                \"Unsupported value type for TIMESTAMP_TZ conversion: \"\n                        + value.getClass().getName()\n                        + \", value='\"\n                        + value\n                        + \"', TiDB dataType=\"\n                        + dataType);\n    }\n\n    private static Object convertToTimestamp(\n            Object value, org.tikv.common.types.DataType dataType) {\n        switch (dataType.getType()) {\n            case TypeTimestamp:\n                if (value instanceof Timestamp) {\n                    Instant instant = ((Timestamp) value).toInstant();\n                    long epochSecond = instant.getEpochSecond();\n                    int nanoSecond = instant.getNano();\n                    long millisecond = epochSecond * 1000L + (long) (nanoSecond / 1000000);\n                    int nanoOfMillisecond = nanoSecond % 1000000;","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-tidb/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/tidb/source/converter/DefaultDataConverter.java#L281-L317","documentation":"When convertToOffsetDateTime receives a TIMESTAMP_TZ value whose type is neither OffsetDateTime, LocalDateTime, Timestamp-like, nor String, it throws an IllegalArgumentException describing the class name, value, and TiDB data type, since no conversion path exists.","triggerScenarios":"convert() passes an unexpected object for a TIMESTAMP_TZ column — e.g. Long epoch millis, java.util.Date, or byte[] — after the String/known-type branches did not match.","commonSituations":"TiDB CDC version change altering emitted classes; schema mismatched so an INT/epoch column mapped to TIMESTAMP_TZ; upstream transform wrapping values.","solutions":["Log/check value.getClass().getName() in the message to identify the actual emitted type","Add a conversion branch for that type (e.g. epoch millis via Instant.ofEpochMilli(...).atZone(...).toOffsetDateTime())","Align connector and TiDB CDC plugin versions so expected classes are emitted","Correct the schema/type mapping so only genuine timestamp values reach TIMESTAMP_TZ conversion"],"exampleFix":"// before\nthrow new IllegalArgumentException(\"Unsupported value type...\");\n// after\nif (value instanceof Long) {\n    return Instant.ofEpochMilli((Long) value).atZone(ZoneId.of(timezone)).toOffsetDateTime();\n}\nthrow new IllegalArgumentException(\"Unsupported value type...\");","handlingStrategy":"type-guard","validationCode":"static boolean isTimestampConvertible(Object v) {\n    return v instanceof OffsetDateTime || v instanceof LocalDateTime\n        || v instanceof String || v instanceof Long || v instanceof java.util.Date;\n}","typeGuard":"static OffsetDateTime toOdtSafe(Object v, ZoneId zone) {\n    if (v instanceof OffsetDateTime) return (OffsetDateTime) v;\n    if (v instanceof LocalDateTime) return ((LocalDateTime) v).atZone(zone).toOffsetDateTime();\n    if (v instanceof Long) return Instant.ofEpochMilli((Long) v).atZone(zone).toOffsetDateTime();\n    if (v instanceof String) return OffsetDateTime.parse(((String) v).replace(' ', 'T'));\n    return null;\n}","tryCatchPattern":"try {\n    return convertToOffsetDateTime(value, dataType);\n} catch (IllegalArgumentException e) {\n    // message already includes class name; route to DLQ or rethrow\n    throw e;\n}","preventionTips":["Log unexpected classes at the boundary and add converter branches for them","Verify schema type mapping so only temporal values reach TIMESTAMP_TZ conversion","Keep connector and TiDB CDC plugin versions aligned"],"tags":["tidb","cdc","timestamp","unsupported-type"],"backgroundTag":"unsupported-operation","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}