apache/seatunnel · warning

Failed to release error sink classloader for jobId=

Error message

Failed to release error sink classloader for jobId={}, pluginName={}, jars={}

What it means

DefaultErrorSinkWriter may load the error-sink plugin with an isolated classloader obtained from the engine's ClassLoaderService. On release, classLoaderService.releaseClassLoader(jobId, jars) threw; Errors are rethrown, but any other Throwable is logged as this warning and cleanup state is still reset. A leaked classloader can retain plugin jars in memory (metaspace pressure) but does not fail the task.

Solutions

  1. Check for duplicate close/release calls in your lifecycle (task retry + close) — this warning then reflects a benign double release.
  2. Verify the ClassLoaderService implementation's release is idempotent and matches how the loader was acquired.
  3. Confirm the jar URLs used at release exactly match those used at acquisition.
  4. Watch metaspace usage; repeated warnings may indicate classloader leaks across jobs.

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try {
    classLoaderService.releaseClassLoader(jobId, jars);
} catch (Throwable e) {
    if (e instanceof Error) throw (Error) e;
    LOG.warn("classloader release failed; possible leak", e);
}

Prevention

When it happens

Trigger: releaseClassLoader throws for the given jobId+jars — e.g. the classloader was never cached for those jars, the cache entry was already released (double release from both close() and ensureInitialized() paths), or the service throws an internal exception.

Common situations: Job cleanup running twice (task retry + final close); engine restart/cleanup racing classloader release; custom ClassLoaderService implementations with non-idempotent release; jar list mutated between acquisition and release.

Related errors


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

Appendix: source

Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/task/error/DefaultErrorSinkWriter.java:697

        }
    }

    private void releaseErrorSinkClassLoaderIfNeeded() {
        if (classLoaderReleased) {
            return;
        }
        List<URL> jars = this.errorSinkPluginJars;
        if (jars == null || jars.isEmpty()) {
            classLoaderReleased = true;
            return;
        }
        try {
            classLoaderService.releaseClassLoader(jobId, jars);
        } catch (Throwable e) {
            if (e instanceof Error) {
                throw (Error) e;
            }
            log.warn(
                    "Failed to release error sink classloader for jobId={}, pluginName={}, jars={}",
                    jobId,
                    sinkConfig.getPluginName(),
                    jars,
                    e);
        } finally {
            classLoaderReleased = true;
            errorSinkPluginJars = null;
            errorSinkClassLoader = null;
        }
    }

    private SeaTunnelRowType buildErrorRowType() {
        List<String> fieldNames = new ArrayList<>();
        List<SeaTunnelDataType<?>> fieldTypes = new ArrayList<>();

        fieldNames.add("error_stage");
        fieldTypes.add(BasicType.STRING_TYPE);

View on GitHub (pinned to cf67b549a7)