{"record":{"id":"4ad791e1c20f2a2b","repo":"apache/seatunnel","slug":"failed-to-parse-postgresql-timestamptz-string-s","errorCode":null,"errorMessage":"Failed to parse PostgreSQL timestamptz string: ${str}","messagePattern":"Failed to parse PostgreSQL timestamptz string: (.+?)","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/dialect/psql/PostgresJdbcRowConverter.java","lineNumber":442,"sourceCode":"            return null;\n        }\n\n        try {\n            return OffsetDateTime.parse(normalized);\n        } catch (Exception primary) {\n            log.debug(\"Failed to parse PostgreSQL timestamptz as ISO-8601: {}\", str, primary);\n            try {\n                String withoutOffset =\n                        normalized.replaceFirst(\"([+-]\\\\d{2}:?\\\\d{2}|\\\\s+UTC|[zZ])$\", \"\");\n                String fallback = withoutOffset.replace('T', ' ').trim();\n                Timestamp ts = Timestamp.valueOf(fallback);\n                return ts.toInstant().atOffset(ZoneOffset.UTC);\n            } catch (Exception secondary) {\n                log.debug(\n                        \"Failed to parse PostgreSQL timestamptz as UTC timestamp: {}\",\n                        str,\n                        secondary);\n                throw new SQLException(\n                        \"Failed to parse PostgreSQL timestamptz string: \" + str, secondary);\n            }\n        }\n    }\n\n    @Nullable private OffsetDateTime parseTimestampFromObjectString(Object obj) throws SQLException {\n        final String str;\n        try {\n            str = String.valueOf(obj);\n        } catch (Throwable e) {\n            log.debug(\n                    \"Failed to get PostgreSQL timestamp object string representation from class: {}\",\n                    obj.getClass().getName(),\n                    e);\n            return null;\n        }\n        return parsePostgresTimestampTz(str);\n    }","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/dialect/psql/PostgresJdbcRowConverter.java#L424-L460","documentation":"Thrown by parsePostgresTimestampTz when a PostgreSQL timestamptz string value cannot be converted to an OffsetDateTime, after a fallback attempt to parse it as a UTC timestamp also failed. The original string and the secondary exception are attached as the cause so the offending value can be inspected.","triggerScenarios":"Reading a timestamptz column via parseTimestampFromObjectString when the JDBC driver returns the value as a String in a format the parser does not recognize (e.g. non-ISO date formats, unusual timezone offsets, or pre-1970 dates before PostgreSQL epoch handling).","commonSituations":"Servers with non-default datestyle/timezone settings producing localized timestamp strings; legacy PostgreSQL versions or drivers returning odd string representations; data migrated with non-standard timestamp formats.","solutions":["Check the actual string value in the exception message and compare it against ISO-8601 expectations","Set the session datestyle/timezone explicitly (e.g. SET datestyle='ISO') on the PostgreSQL connection so the driver returns parseable strings","Upgrade the PostgreSQL JDBC driver so timestamptz columns come back as OffsetDateTime/Timestamp objects instead of Strings","Pre-cast the column in the SQL query: CAST(col AS text) with an explicit format, or select via to_char(col, 'YYYY-MM-DD\"T\"HH24:MI:SSOF')"],"exampleFix":"// before\nString raw = rs.getString(\"created_at\");\n// after\nOffsetDateTime odt = rs.getObject(\"created_at\", OffsetDateTime.class); // avoid string parsing path","handlingStrategy":"try-catch","validationCode":"// Pre-validate string before relying on connector parsing\nboolean parseable;\ntry {\n    java.time.OffsetDateTime.parse(str);\n    parseable = true;\n} catch (java.time.format.DateTimeParseException e) {\n    parseable = false;\n}","typeGuard":"static boolean isIsoTimestamptz(String s) {\n    return s != null && java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(s, java.time.temporal.TemporalQueries.offset()) != null;\n}","tryCatchPattern":"try {\n    runJob();\n} catch (SQLException e) {\n    if (e.getMessage().startsWith(\"Failed to parse PostgreSQL timestamptz string:\")) {\n        // log raw value from message, fix session datestyle or pre-format column\n    }\n}","preventionTips":["Force ISO datestyle in the PostgreSQL session (SET datestyle='ISO, MDY')","Prefer SELECTing timestamptz columns as OffsetDateTime objects, not strings","Upgrade the PostgreSQL JDBC driver","Test with rows in non-UTC timezones and pre-1970 dates"],"tags":["jdbc","postgresql","timestamp","date-parsing"],"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"}