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

  1. Check connectivity to the Pulsar admin service URL; this error usually reflects an already-broken connection.
  2. Inspect the wrapped cause (PulsarAdminException) for the real reason (timeout, auth, connection reset).
  3. If it appears only at shutdown after a normal job completion, it is largely benign — resources are released on process teardown anyway.
  4. 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

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


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