{"record":{"id":"1f71a5b26c024284","repo":"apache/seatunnel","slug":"unable-to-convert-timestamp-tz-from-string-value","errorCode":null,"errorMessage":"Unable to convert TIMESTAMP_TZ from String value: '${value}' for TiDB dataType: ${dataType}","messagePattern":"Unable to convert TIMESTAMP_TZ from String value: '(.+?)' for 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":289,"sourceCode":"        if (value instanceof Timestamp) {\n            // TiDB TIMESTAMP is stored in UTC; convert to OffsetDateTime with UTC zone.\n            Instant instant = ((Timestamp) value).toInstant();\n            return OffsetDateTime.ofInstant(instant, ZoneOffset.UTC);\n        }\n        if (value instanceof Long) {\n            // TiDB may emit TIMESTAMP as epoch milliseconds in some snapshot modes.\n            return OffsetDateTime.ofInstant(Instant.ofEpochMilli((Long) value), ZoneOffset.UTC);\n        }\n        if (value instanceof LocalDateTime) {\n            // 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","sourceCodeStart":271,"sourceCodeEnd":307,"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#L271-L307","documentation":"convertToOffsetDateTime converts TIMESTAMP_TZ values to OffsetDateTime; when the value is a String it attempts strict ISO-8601 OffsetDateTime.parse. A parse failure raises an IllegalArgumentException including the raw string and the TiDB data type.","triggerScenarios":"A TIMESTAMP/TIMESTAMPTZ column whose value reaches the converter as a String that is not valid ISO-8601 with offset — e.g. '2024-01-01 10:00:00' (space, no zone) or missing offset.","commonSituations":"TiDB DATETIME/TIMESTAMP emitted as 'yyyy-MM-dd HH:mm:ss' without timezone; fractional seconds beyond ISO parsing tolerance; server timezone configured differently than expected.","solutions":["Use a formatter matching TiDB's 'yyyy-MM-dd HH:mm:ss[.SSSSSS]' and attach the configured zone instead of OffsetDateTime.parse","Set an explicit timezone in the connector/job config so strings are parsed with the intended offset","Normalize the value (replace space with 'T', append offset) before parsing","Catch DateTimeParseException upstream and fall back to a lenient parser"],"exampleFix":"// before\nreturn OffsetDateTime.parse((String) value);\n// after\nLocalDateTime ldt = LocalDateTime.parse(((String) value).replace(' ', 'T'));\nreturn ldt.atZone(ZoneId.of(timezone)).toOffsetDateTime();","handlingStrategy":"validation","validationCode":"static boolean isIsoOffsetDateTime(String s) {\n    try { OffsetDateTime.parse(s); return true; } catch (DateTimeParseException e) { return false; }\n}\n// normalize first: s = s.replace(' ', 'T'); append zone offset if absent","typeGuard":"static boolean looksLikeTimestamp(String s) {\n    return s != null && s.matches(\"\\\\d{4}-\\\\d{2}-\\\\d{2}[ T]\\\\d{2}:\\\\d{2}:\\\\d{2}(.\\\\d+)?(Z|[+-]\\\\d{2}:?\\\\d{2})?\");\n}","tryCatchPattern":"try {\n    return convertToOffsetDateTime(value, dataType);\n} catch (IllegalArgumentException e) {\n    log.error(\"TIMESTAMP_TZ parse failure for value '{}': {}\", value, e.getMessage());\n    throw e;\n}","preventionTips":["Normalize TiDB 'yyyy-MM-dd HH:mm:ss' strings to ISO-8601 before conversion","Configure an explicit timezone so offsets are known","Test with fractional-second values from your TiDB deployment"],"tags":["tidb","cdc","timestamp","datetime-parse"],"backgroundTag":"invalid-date-format","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"}