apache/seatunnel · error · IOException

Failed to close Pulsar sink writer.

Error message

Failed to close Pulsar sink writer.

What it means

PulsarSinkWriter.rethrowCloseFailure normalizes any non-IOException/non-RuntimeException throwable raised while releasing producers/client/transactions during close() into a plain IOException with this message, preserving the original as the cause. It signals resource cleanup failed (e.g. an Error or checked non-IO exception).

Source

Thrown at seatunnel-connectors-v2/connector-pulsar/src/main/java/org/apache/seatunnel/connectors/seatunnel/pulsar/sink/PulsarSinkWriter.java:395

                throwable);
    }

    private Throwable appendSuppressed(Throwable existingFailure, Throwable newFailure) {
        if (existingFailure == null) {
            return newFailure;
        }
        existingFailure.addSuppressed(newFailure);
        return existingFailure;
    }

    private void rethrowCloseFailure(Throwable throwable) throws IOException {
        if (throwable instanceof IOException) {
            throw (IOException) throwable;
        }
        if (throwable instanceof RuntimeException) {
            throw (RuntimeException) throwable;
        }
        throw new IOException("Failed to close Pulsar sink writer.", throwable);
    }

    @Override
    public MultiTableResourceManager<Void> initMultiTableResourceManager(
            int tableSize, int queueSize) {
        return null;
    }

    @Override
    public void setMultiTableResourceManager(
            MultiTableResourceManager<Void> multiTableResourceManager, int queueIndex) {
        // Pulsar sink does not require shared resources across tables
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Inspect the cause chain in the stack trace for the underlying close/flush failure and fix that root cause.
  2. Ensure pending async sends succeed (broker reachable, producer healthy) before job teardown.
  3. Upgrade/align the Pulsar client version if an unexpected exception class escapes cleanup.

Example fix

// before
// writer.close() throws IOException caused by Error during cleanup
// after: log & fix root cause, e.g. guard custom classloader usage
try (final PulsarSinkWriter w = createWriter()) {
  w.write(row);
} // ensure close succeeds; inspect cause if this error appears
Defensive patterns

Strategy: try-catch

Try / catch

try {
    writer.close();
} catch (IOException e) {
    log.error("Pulsar sink writer close failed; inspect cause", e);
    throw e; // rethrow to fail the task, cause holds the real error
}

Prevention

When it happens

Trigger: close() accumulates a throwable from closing producers, flushing pending sends, or closing the PulsarClient/transaction, and the throwable is neither IOException nor RuntimeException; rethrowCloseFailure wraps it.

Common situations: Async send failures surfacing during flush-on-close; errors thrown by custom classloader cleanup (see related tests); JVM-level Error (e.g. OOM) during close; unexpected library exception type from a Pulsar client upgrade.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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