{"record":{"id":"969b95da03453ea3","repo":"apache/seatunnel","slug":"unable-to-parse-offsetdatetime-from-cdc-timestamp","errorCode":null,"errorMessage":"Unable to parse OffsetDateTime from CDC TIMESTAMP_TZ value: ''. Supported formats: ISO-8601 with numeric offset, IANA zone-region id, space-separated date/time, short-form hour-only offset, UTC epoch literal.","messagePattern":"Unable to parse OffsetDateTime from CDC TIMESTAMP_TZ value: ''\\. Supported formats: ISO-8601 with numeric offset, IANA zone-region id, space-separated date/time, short-form hour-only offset, UTC epoch literal\\.","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/debezium/row/SeaTunnelRowDebeziumDeserializationConverters.java","lineNumber":514,"sourceCode":"            // fall through\n        }\n\n        // 3. Space separator or short offset: 2024-01-01 12:00:00+08:00 / +08\n        try {\n            return java.time.OffsetDateTime.parse(str, FLEXIBLE_OFFSET_FORMATTER)\n                    .withOffsetSameInstant(java.time.ZoneOffset.UTC);\n        } catch (java.time.format.DateTimeParseException ignored) {\n            // fall through\n        }\n\n        // 4. UTC epoch literal: 2024-01-01T12:00:00Z\n        try {\n            return Instant.parse(str).atOffset(java.time.ZoneOffset.UTC);\n        } catch (java.time.format.DateTimeParseException ignored) {\n            // fall through\n        }\n\n        throw new IllegalArgumentException(\n                \"Unable to parse OffsetDateTime from CDC TIMESTAMP_TZ value: '\"\n                        + str\n                        + \"'. Supported formats: ISO-8601 with numeric offset, IANA zone-region\"\n                        + \" id, space-separated date/time, short-form hour-only offset, UTC\"\n                        + \" epoch literal.\");\n    }\n\n    private static DebeziumDeserializationConverter convertToTimestamp(ZoneId serverTimeZone) {\n        return new DebeziumDeserializationConverter() {\n            private static final long serialVersionUID = 1L;\n\n            @SuppressWarnings(\"MagicNumber\")\n            @Override\n            public Object convert(Object dbzObj, Schema schema) {\n                if (dbzObj instanceof Long) {\n                    switch (schema.name()) {\n                        case Timestamp.SCHEMA_NAME:\n                            return toLocalDateTime((Long) dbzObj, 0);","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/debezium/row/SeaTunnelRowDebeziumDeserializationConverters.java#L496-L532","documentation":"parseOffsetDateTimeFromString() converts a CDC TIMESTAMP_TZ string value to an OffsetDateTime. It tries multiple formats: ISO-8601 with offset, IANA region id, space-separated datetime, short hour-only offset, and Instant/epoch literal. When the string matches none, it throws IllegalArgumentException listing all supported formats.","triggerScenarios":"A TIMESTAMP_TZ CDC value that is empty, null-rendered as '', or formatted in a non-ISO layout (e.g. custom driver string or locale-dependent text) reaches convert() -> parseOffsetDateTimeFromString().","commonSituations":"Empty string timestamps from some database drivers or placeholder values (e.g. '0000-00-00 00:00:00' style zero dates from MySQL), or a date-time format not covered by the parser branches.","solutions":["Fix the source data: replace empty/zero-date timestamp values with valid timestamps (e.g. NULL or a sentinel like '1970-01-01T00:00:00Z').","Ensure the column produces ISO-8601 or IANA-zone formatted values; add a converter/transform to normalize before deserialization.","Check the exact offending value in the message; if it is a legitimate new format, extend the parser chain in SeaTunnelRowDebeziumDeserializationConverters."],"exampleFix":"// before\n// source contains '' or '0000-00-00 00:00:00' for TIMESTAMP_TZ\n// after\nUPDATE t SET ts = NULL WHERE ts = '0000-00-00 00:00:00';\n// or configure the job to map invalid dates to null/sentinel","handlingStrategy":"validation","validationCode":"// Java: pre-validate CDC timestamp strings\nstatic boolean isParsableTimestampTz(String s) {\n    if (s == null || s.isEmpty()) return false;\n    try { OffsetDateTime.parse(s); return true; } catch (Exception ignored) {}\n    try { ZoneId.of(s); return true; } catch (Exception ignored) {}\n    try { Instant.parse(s); return true; } catch (Exception ignored) {}\n    return s.matches(\"[+-]\\\\d{2}(:?\\\\d{2})?\") || s.matches(\"\\\\d{4}-\\\\d{2}-\\\\d{2} \\\\d{2}:\\\\d{2}(:\\\\d{2})?\");\n}","typeGuard":"if (v == null || (v instanceof String && ((String) v).trim().isEmpty())) {\n    return null; // treat empty TIMESTAMP_TZ as null before parsing\n}","tryCatchPattern":"try {\n    odt = parseOffsetDateTimeFromString(str);\n} catch (IllegalArgumentException e) {\n    log.warn(\"unparseable TIMESTAMP_TZ '{}', substituting null/sentinel\", str);\n    odt = null;\n}","preventionTips":["Scrub zero-date/empty timestamp values at the source (e.g. MySQL sql_mode NO_ZERO_DATE, NULL instead of '0000-00-00')","Emit TIMESTAMP_TZ in ISO-8601 or IANA zone form from producers","Add a job-level transform to normalize or null-out invalid datetimes before deserialization"],"tags":["cdc","datetime","parse","timestamp"],"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"}