apache/seatunnel · error · DebeziumException

Failed to resolve snapshot offset

Error message

Failed to resolve snapshot offset

What it means

getPendingTransactionsFromLogs starts a LogMiner session to mine redo logs for transactions that were in-flight during the snapshot, so their start SCNs can be recorded in the offset. Any exception thrown during this log-mining pass (JDBC errors, LogMiner session failures, query errors) is wrapped in this DebeziumException, and the caller determineSnapshotOffset then fails the snapshot.

Solutions

  1. Read the wrapped cause for the specific ORA- error and fix accordingly (e.g. restore/pin archive logs for the mining window)
  2. Grant the connector user LogMiner-related privileges and access to the log mining dictionary
  3. Ensure archive logs covering the snapshot SCN range are retained (increase RMAN retention / avoid deleting active logs)
  4. Re-run the snapshot after fixing log retention or privilege issues
Defensive patterns

Strategy: try-catch

Validate before calling

-- Ensure archive logs covering the snapshot window are retained:
SELECT NAME, FIRST_CHANGE#, NEXT_CHANGE#, DELETED FROM V$ARCHIVED_LOG ORDER BY FIRST_CHANGE#;
-- RMAN: CONFIGURE RETENTION POLICY ... ; do not delete logs still needed

Try / catch

try {
    adapter.determineSnapshotOffset(...);
} catch (DebeziumException e) {
    if (e.getMessage().startsWith("Failed to resolve snapshot offset") && e.getCause() != null) {
        logOraError(e.getCause()); // inspect ORA- code, fix retention/privileges, then retry snapshot
    } else { throw e; }
}

Prevention

When it happens

Trigger: determineSnapshotOffset -> getPendingTransactionsFromLogs executes the LogMiner mining loop over v$logmnr_contents; the underlying query/session throws (invalid STARTSCN, missing archive logs, ORA- errors from LogMiner, insufficient privileges).

Common situations: Required redo/archive logs already purged so the mining window is invalid; LogMiner session start fails due to permissions or dictionary issues; long-running snapshot transactions exceed retained logs; Oracle raises ORA-01291 (missing logfile).

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


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

Appendix: source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle/src/main/java/io/debezium/connector/oracle/logminer/LogMinerAdapter.java:389

                        rs -> {
                            while (rs.next()) {
                                final String transactionId =
                                        HexConverter.convertToHexString(rs.getBytes("XID"));
                                final String startScnStr = rs.getString("START_SCN");
                                if (!Strings.isNullOrBlank(startScnStr)) {
                                    final Scn startScn = Scn.valueOf(rs.getString("START_SCN"));
                                    if (!pendingTransactions.containsKey(transactionId)) {
                                        LOGGER.info(
                                                "\tTransaction '{}' started at SCN '{}'",
                                                transactionId,
                                                startScn);
                                        pendingTransactions.put(transactionId, startScn);
                                    }
                                }
                            }
                        });
            } catch (Exception e) {
                throw new DebeziumException("Failed to resolve snapshot offset", e);
            } finally {
                stopSession(connection);
            }
        }
    }

    private List<LogFile> getMostRecentLogFilesForSearch(List<LogFile> allLogFiles) {
        Map<Integer, List<LogFile>> recentLogsPerThread = new HashMap<>();
        for (LogFile logFile : allLogFiles) {
            if (!recentLogsPerThread.containsKey(logFile.getThread())) {
                if (logFile.isCurrent()) {
                    recentLogsPerThread.put(logFile.getThread(), new ArrayList<>());
                    recentLogsPerThread.get(logFile.getThread()).add(logFile);
                    final Optional<LogFile> maxArchiveLogFile =
                            allLogFiles.stream()
                                    .filter(
                                            f ->
                                                    logFile.getThread() == f.getThread()

View on GitHub (pinned to cf67b549a7)