apache/seatunnel · warning
Cannot drop replication slot '{}' because it's still in use
Error message
Cannot drop replication slot '{}' because it's still in use What it means
dropReplicationSlot tried to drop a replication slot via pg_drop_replication_slot but the PostgreSQL backend reports SQLSTATE 55006 (OBJECT_IN_USE) because a session is still streaming from the slot. It retries ATTEMPTS times, then warns and returns false (slot not dropped).
Source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-opengauss/src/main/java/io/debezium/connector/postgresql/connection/PostgresConnection.java:458
*
* @param slotName the name of the replication slot, may not be null
* @return {@code true} if the slot was dropped, {@code false} otherwise
*/
public boolean dropReplicationSlot(String slotName) {
final int ATTEMPTS = 3;
for (int i = 0; i < ATTEMPTS; i++) {
try {
execute("select pg_drop_replication_slot('" + slotName + "')");
return true;
} catch (SQLException e) {
// slot is active
if (PSQLState.OBJECT_IN_USE.getState().equals(e.getSQLState())) {
if (i < ATTEMPTS - 1) {
LOGGER.debug(
"Cannot drop replication slot '{}' because it's still in use",
slotName);
} else {
LOGGER.warn(
"Cannot drop replication slot '{}' because it's still in use",
slotName);
return false;
}
} else if (PSQLState.UNDEFINED_OBJECT.getState().equals(e.getSQLState())) {
LOGGER.debug("Replication slot {} has already been dropped", slotName);
return false;
} else {
LOGGER.error("Unexpected error while attempting to drop replication slot", e);
return false;
}
}
try {
Metronome.parker(Duration.ofSeconds(1), Clock.system()).pause();
} catch (InterruptedException e) {
}
}
return false;View on GitHub (pinned to cf67b549a7)
Solutions
- Find and terminate the backend holding the slot: SELECT pg_terminate_backend(active_pid) FROM pg_replication_slots WHERE slot_name='<slot>'; then retry the drop.
- Close all other replication connections using the slot before dropping it.
- Wait for the streaming session to end (slot active=false in pg_replication_slots) and retry.
- If the slot must go regardless, run SELECT pg_drop_replication_slot('<slot>'); manually after terminating the holder.
Example fix
// before
dropReplicationSlot("dbz"); // returns false, slot in use
// after
// stmt.execute("SELECT pg_terminate_backend(active_pid) FROM pg_replication_slots WHERE slot_name='dbz' AND active");
// then dropReplicationSlot("dbz"); Defensive patterns
Strategy: try-catch
Validate before calling
SELECT active, active_pid FROM pg_replication_slots WHERE slot_name='<slot>'; -- only drop when active=false
Try / catch
try { boolean dropped = conn.dropReplicationSlot(slot); if (!dropped) { terminateHolderPid(slot); retryDrop(slot); } } catch (SQLException e) { /* handle */ } Prevention
- Check slot active=false before dropping.
- Terminate streaming backends via pg_terminate_backend first.
- Close connector tasks gracefully before cleanup.
When it happens
Trigger: Calling connection.dropReplicationSlot(slotName) while another connection/thread holds an active replication stream on that slot; the last retry hits OBJECT_IN_USE again and returns false.
Common situations: Connector restart while the old task still streams; a orphaned walreceiver backend keeping the slot active; tests shutting down a connection while the replicator thread is alive; killing a job whose streaming connection hasn't been released server-side yet.
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
- No replication slot found
- Unable to parse create_replication_slot response
- READ_COMMITTED_OFFSET_FAILED
- Creation of replication slot failed
- Cannot obtain valid replication slot '{}' for plugin '{}' an
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/ce0a710b60b250c6.
Report an issue: GitHub.