apache/seatunnel · warning · IOException
Failed to close Pulsar admin.
Error message
Failed to close Pulsar admin.
What it means
PulsarSplitEnumerator.close shuts down its executor and closes the PulsarAdmin client. If pulsarAdmin.close() (run under the connector classloader) throws, the IOException is wrapped as 'Failed to close Pulsar admin.' This is a cleanup-path error: the job/task was stopping but the admin client could not be released cleanly.
Source
Thrown at seatunnel-connectors-v2/connector-pulsar/src/main/java/org/apache/seatunnel/connectors/seatunnel/pulsar/source/enumerator/PulsarSplitEnumerator.java:279
if (noMoreNewPartitionSplits && boundedness == Boundedness.BOUNDED) {
LOG.debug(
"No more PulsarPartitionSplits to assign. Sending NoMoreSplitsEvent to reader {}.",
pendingReaders);
pendingReaders.forEach(context::signalNoMoreSplits);
}
}
@Override
public void close() throws IOException {
if (executor != null) {
// Stop periodic discovery before closing the shared admin client it uses.
executor.shutdownNow();
}
if (pulsarAdmin != null) {
try {
PulsarConfigUtil.runWithConnectorClassLoader(pulsarAdmin::close);
} catch (Exception e) {
throw new IOException("Failed to close Pulsar admin.", e);
}
}
}
@Override
public void addSplitsBack(List<PulsarPartitionSplit> splits, int subtaskId) {
addPartitionSplitChangeToPendingAssignments(splits);
// If the failed subtask has already restarted, we need to assign pending splits to it
if (context.registeredReaders().contains(subtaskId)) {
assignPendingPartitionSplits(Collections.singleton(subtaskId));
}
}
@Override
public int currentUnassignedSplitSize() {
return pendingPartitionSplits.size();
}View on GitHub (pinned to cf67b549a7)
Solutions
- Check connectivity to the Pulsar admin service URL; this error usually reflects an already-broken connection.
- Inspect the wrapped cause (PulsarAdminException) for the real reason (timeout, auth, connection reset).
- If it appears only at shutdown after a normal job completion, it is largely benign — resources are released on process teardown anyway.
- Ensure firewall/idle-timeout settings don't kill long-lived admin connections mid-job; tune keepalive.
Defensive patterns
Strategy: try-catch
Validate before calling
checkAdminServiceReachable(cfg.getString("admin.service-url")); // HTTP HEAD before job start Try / catch
try {
enumerator.close();
} catch (IOException e) {
LOG.warn("Pulsar admin close failed at shutdown; cause: {}", e.getCause(), e);
} Prevention
- Verify admin.service-url reachability before starting jobs.
- Treat close-time failures after normal completion as benign warnings.
- Check firewall/idle timeouts that sever long-lived admin connections.
When it happens
Trigger: Calling PulsarSplitEnumerator.close() while the PulsarAdmin client's underlying connection is broken, the admin service is unreachable, or the close call is interrupted/fails inside PulsarConfigUtil.runWithConnectorClassLoader.
Common situations: Job cancellation during a Pulsar broker/admin outage; network partitions between SeaTunnel workers and the Pulsar admin service; classloader issues in plugin deployments.
Related errors
- Error while closing pulsar consumer
- Error closing MQTT client
- PulsarConnectorErrorCode.GET_LAST_CURSOR_FAILED
- Failed to close Pulsar consumer.
- Failed to close Fluss admin for {}
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/0f1b474e44a2d364.
Report an issue: GitHub.