apache/seatunnel · error · SeaTunnelException

Cannot convert timestamp to SCN. Make sure the specified…

Error message

Cannot convert timestamp to SCN. Make sure the specified timestamp is valid.

What it means

OracleConnectionUtils.timestampToScn converts a timestamp to an SCN using Oracle's TIMESTAMP_TO_SCN function and throws SeaTunnelException if the query returns no row, meaning no SCN could be associated with the given timestamp. Oracle cannot map timestamps outside the range retained by its SCN-to-time mapping (bounded by undo/flashback and database uptime).

Solutions

  1. Use a more recent timestamp within Oracle's SCN mapping retention (typically only hours to a few days)
  2. Use startup.mode=latest or initial instead of timestamp for old starting points
  3. Align serverTimeZone config with the Oracle server time zone
  4. Check DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER availability and flashback configuration

Example fix

// before
scan.startup.mode = timestamp
scan.startup.timestamp = 1724000000000  // weeks old -> no SCN mapping
// after
scan.startup.mode = latest
Defensive patterns

Strategy: validation

Validate before calling

long minBack = System.currentTimeMillis() - Duration.ofHours(1).toMillis();
if (timestamp <= 0 || timestamp > System.currentTimeMillis() || timestamp < minBack) {
    throw new IllegalArgumentException("timestamp outside SCN-mapping range; use a recent timestamp or startup.mode=latest");
}

Try / catch

try {
    RedoLogOffset off = OracleConnectionUtils.timestampToScn(conn, ts, tz);
} catch (SeaTunnelException e) {
    LOG.warn("No SCN for timestamp {}; fall back to latest", ts);
    // fallback: use currentRedoLogOffset(conn)
}

Prevention

When it happens

Trigger: Calling timestampToScn with a timestamp too old (beyond the SCN time mapping retention), a future timestamp, or a timestamp in the wrong time zone so the mapping query yields no result.

Common situations: startup.mode=timestamp with start time days/weeks in the past; recently restarted database losing older SCN-time mappings; time zone mismatch between configured serverTimeZone and actual DB time zone.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/203d9ee18bfa06b7. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/oracle/utils/OracleConnectionUtils.java:121

                    "Converting timestamp {} to SCN with server time zone {}",
                    timestampMs,
                    effectiveServerTimeZone);
            String sql = "SELECT TIMESTAMP_TO_SCN(?) AS SCN FROM DUAL";
            return jdbc.prepareQueryAndMap(
                    sql,
                    statement -> {
                        java.sql.Timestamp timestamp = new java.sql.Timestamp(timestampMs);
                        Calendar calendar =
                                Calendar.getInstance(TimeZone.getTimeZone(effectiveServerTimeZone));
                        statement.setTimestamp(1, timestamp, calendar);
                    },
                    rs -> {
                        if (rs.next()) {
                            final String scn = rs.getString(1);
                            LOG.info("Converted timestamp {} to SCN: {}", timestampMs, scn);
                            return new RedoLogOffset(Scn.valueOf(scn).longValue());
                        } else {
                            throw new SeaTunnelException(
                                    "Cannot convert timestamp to SCN. Make sure the specified timestamp is valid.");
                        }
                    });
        } catch (SQLException e) {
            LOG.error("Failed to convert timestamp to SCN", e);
            throw new SeaTunnelException("Failed to convert timestamp to SCN", e);
        }
    }

    public static List<TableId> listTables(
            JdbcConnection jdbcConnection, String database, RelationalTableFilters tableFilters)
            throws SQLException {
        final List<TableId> capturedTableIds = new ArrayList<>();

        Set<TableId> tableIdSet = new HashSet<>();
        String queryTablesSql =
                "SELECT OWNER ,TABLE_NAME,TABLESPACE_NAME FROM ALL_TABLES \n"
                        + "WHERE PARTITIONED = 'YES' OR (TABLESPACE_NAME IS NOT NULL AND TABLESPACE_NAME NOT IN ('SYSAUX'))";

View on GitHub (pinned to cf67b549a7)