apache/seatunnel · error · ConnectException

Unable to obtain valid replication slot. Make sure there are

Error message

Unable to obtain valid replication slot. Make sure there are no long-running transactions running in parallel as they may hinder the allocation of the replication slot when starting this connector

What it means

PostgresConnection.readReplicationSlotInfo retries up to MAX_ATTEMPTS_FOR_OBTAINING_REPLICATION_SLOT to read a valid replication slot from pg_replication_slots, pausing between attempts via a metronome. When no valid slot is found after all attempts, it throws this ConnectException. The connector requires a usable logical replication slot to stream WAL changes, and concurrent long-running transactions can hold back slot creation/visibility.

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-opengauss/src/main/java/io/debezium/connector/postgresql/connection/PostgresConnection.java:351

                Metronome.parker(PAUSE_BETWEEN_REPLICATION_SLOT_RETRIEVAL_ATTEMPTS, Clock.SYSTEM);

        for (int attempt = 1; attempt <= MAX_ATTEMPTS_FOR_OBTAINING_REPLICATION_SLOT; attempt++) {
            final ServerInfo.ReplicationSlot slot = fetchReplicationSlotInfo(slotName, pluginName);
            if (slot != null) {
                LOGGER.info("Obtained valid replication slot {}", slot);
                return slot;
            }
            LOGGER.warn(
                    "Cannot obtain valid replication slot '{}' for plugin '{}' and database '{}' [during attempt {} out of {}, concurrent tx probably blocks taking snapshot.",
                    slotName,
                    pluginName,
                    database,
                    attempt,
                    MAX_ATTEMPTS_FOR_OBTAINING_REPLICATION_SLOT);
            metronome.pause();
        }

        throw new ConnectException(
                "Unable to obtain valid replication slot. "
                        + "Make sure there are no long-running transactions running in parallel as they may hinder the allocation of the replication slot when starting this connector");
    }

    protected ServerInfo.ReplicationSlot queryForSlot(
            String slotName,
            String database,
            String pluginName,
            ResultSetMapper<ServerInfo.ReplicationSlot> map)
            throws SQLException {
        return prepareQueryAndMap(
                "select * from pg_replication_slots where slot_name = ? and database = ? and plugin = ?",
                statement -> {
                    statement.setString(1, slotName);
                    statement.setString(2, database);
                    statement.setString(3, pluginName);
                },
                map);

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Verify the slot exists: SELECT * FROM pg_replication_slots WHERE slot_name = '<slot>'; and create it manually if missing (SELECT pg_create_logical_replication_slot('<slot>','<plugin>')).
  2. Find and terminate long-running transactions: SELECT pid, state, xact_start FROM pg_stat_activity WHERE state = 'idle in transaction'; then pg_terminate_backend(pid).
  3. Check that the connector's slot_name and plugin (pgoutput/decoderbufs) match the server configuration and wal_level=logical.
  4. Restart the connector once the slot is healthy; if retries keep failing, increase the retry attempts/max delay if configurable.

Example fix

-- before: connector fails at startup, slot missing
-- after: create the slot manually before starting
SELECT pg_create_logical_replication_slot('seatunnel_slot', 'pgoutput');
-- terminate blocking transactions
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle in transaction' AND xact_start < now() - interval '1 hour';
Defensive patterns

Strategy: validation

Validate before calling

SELECT slot_name, plugin, active FROM pg_replication_slots WHERE slot_name = 'seatunnel_slot'; -- must return exactly one row before starting the connector
SELECT pid FROM pg_stat_activity WHERE state = 'idle in transaction' AND xact_start < now() - interval '10 minutes'; -- should return 0 rows

Prevention

When it happens

Trigger: getReplicationSlotState/readReplicationSlotInfo polls pg_replication_slots for the configured slot name and the query returns no row (or an invalid slot) on every one of the configured attempts, typically because the slot was not yet created, was dropped, or its creation is blocked by an open transaction holding the XID horizon.

Common situations: Another pipeline or a crashed previous run dropped the slot; a long-lived transaction (e.g. an idle-in-transaction session or an analytics query) prevents slot allocation; slot_name mismatch between connector config and the actual slot on the server; running against a replica that cannot provide the slot.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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