apache/seatunnel · error · RuntimeException
received unexpected exception will perform keep alive
Error message
received unexpected exception will perform keep alive
What it means
The keep-alive thread that periodically forces status updates on the replication stream hit an unexpected exception (e.g. the stream/socket broke, or the backend terminated). startKeepAlive wraps any exception from stream.forceUpdateStatus() in a RuntimeException with this message, since failing to send keep-alives will let the server drop the slot/WAL.
Source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-opengauss/src/main/java/io/debezium/connector/postgresql/connection/PostgresReplicationConnection.java:667
public Lsn lastReceivedLsn() {
return lastReceivedLsn;
}
@Override
public void startKeepAlive(ExecutorService service) {
if (keepAliveExecutor == null) {
keepAliveExecutor = service;
keepAliveRunning = new AtomicBoolean(true);
keepAliveExecutor.submit(
() -> {
while (keepAliveRunning.get()) {
try {
LOGGER.trace(
"Forcing status update with replication stream");
stream.forceUpdateStatus();
metronome.pause();
} catch (Exception exp) {
throw new RuntimeException(
"received unexpected exception will perform keep alive",
exp);
}
}
});
}
}
@Override
public void stopKeepAlive() {
if (keepAliveExecutor != null) {
keepAliveRunning.set(false);
keepAliveExecutor.shutdownNow();
keepAliveExecutor = null;
}
}
private void processWarnings(final boolean forced) throws SQLException {View on GitHub (pinned to cf67b549a7)
Solutions
- Inspect the wrapped cause (exp) to find the real failure — usually a broken replication connection
- Restart the connector/task so the replication connection is re-established (Debezium will resume from the last confirmed LSN)
- Ensure network devices do not kill idle connections; keep keep-alive interval below firewall/timeout thresholds
- Fix shutdown ordering so the keep-alive thread is stopped before the stream is closed
Defensive patterns
Strategy: retry
Validate before calling
// Check network stability to the DB before starting: // SELECT 1 FROM pg_stat_replication; and verify no firewall drops long-lived TCP sessions
Try / catch
try {
keepAliveFuture.get(timeout, TimeUnit.SECONDS);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause.getMessage() != null && cause.getMessage().contains("received unexpected exception will perform keep alive")) {
// underlying replication connection broke: reconnect/resume streaming from last confirmed LSN
restartStreamingTask();
}
} Prevention
- Keep keep-alive interval below firewall/NAT idle timeouts
- Monitor replication connection health (pg_stat_replication)
- Ensure clean shutdown stops the keep-alive scheduler before closing the stream
- Tune TCP keepalives on the JDBC/replication connection
When it happens
Trigger: startKeepAlive's scheduled metronome task calls stream.forceUpdateStatus() and the underlying PGStream throws (connection dropped by server/network, thread interrupted, stream already closed because main streaming failed).
Common situations: Network partitions or firewall idle timeouts killing the replication connection; PostgreSQL restart during keep-alive; connector shutting down while the keep-alive executor is still running; long GC pause causing socket timeout.
Related errors
- Interrupted while waiting for valid replication slot info
- The offset to start reading from has been removed from the d
- CREATE_REPLICATION_CONNECTION_FAILED
- Error getting current Lsn/txId ${e.getMessage()}
- Connection retry sleep interrupted by exception:
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/47670120e013478d.
Report an issue: GitHub.