apache/seatunnel · error · UnsupportedOperationException
can't support custom load jar
Error message
can't support custom load jar
What it means
AbstractPluginDiscovery's DEFAULT_URL_TO_CLASSLOADER adds plugin jar URLs to a classloader via reflection, but only when the classloader is a URLClassLoader. On modern JDKs (9+) the application classloader is not a URLClassLoader, so any attempt to add custom plugin jar URLs throws UnsupportedOperationException('can't support custom load jar'). This fires in the discovery constructor when dynamic plugin jar loading is requested.
Solutions
- Place the plugin jar into the SeaTunnel plugin directory (connectors/ or lib/) so it is loaded at startup instead of dynamically
- Run on a JDK/mode where the classloader is a URLClassLoader, or launch with a custom URLClassLoader setup
- Remove the plugin jar path configuration so discovery uses classpath-based loading
Example fix
// before (config referencing external jar) plugin_jar_paths = ["/opt/my/custom-connector.jar"] // after # remove the jar path config; install the jar instead: cp /opt/my/custom-connector.jar $SEATUNNEL_HOME/connectors/
Defensive patterns
Strategy: fallback
Validate before calling
ClassLoader cl = Thread.currentThread().getContextClassLoader();
boolean dynamicJarLoadingSupported = cl instanceof URLClassLoader;
if (!dynamicJarLoadingSupported) {
// do not configure plugin jar URLs; place jars in the plugin dir instead
} Type guard
boolean supportsDynamicJarAdd(ClassLoader cl) {
return cl instanceof URLClassLoader;
} Try / catch
try {
discovery = new MyPluginDiscovery(pluginDir, pluginJars);
} catch (UnsupportedOperationException e) {
if ("can't support custom load jar".equals(e.getMessage())) {
log.warn("Dynamic jar loading unsupported on this JDK; install jars into the plugin dir instead");
} else {
throw e;
}
} Prevention
- Install plugins into $SEATUNNEL_HOME/connectors or lib instead of runtime jar injection
- On JDK 9+ never rely on adding URLs to the app classloader
- Document that custom jar paths require a URLClassLoader-based launch
When it happens
Trigger: Constructing an AbstractPluginDiscovery subclass with plugin jar URLs while running on a JDK whose application classloader is not a URLClassLoader (Java 9+), i.e. dynamic 'custom load jar' is requested but unsupported by the runtime.
Common situations: Running SeaTunnel on JDK 9+ where custom plugin jar loading was attempted; configuring plugin jar paths on a runtime that does not support adding URLs; launching the engine in a mode that expects dynamic jar injection.
Understand the failure class
Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.
Related errors
- CONFIG_VALIDATION_FAILED
- get plugin dependency jar path failed, pluginIdentifier
- plugin dir: not exists, load plugin from classpath
- Plugin not found.
- A decoding format must override this method to apply…
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/0a53e084ff4b0f54.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-plugin-discovery/src/main/java/org/apache/seatunnel/plugin/discovery/AbstractPluginDiscovery.java:85
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Slf4j
@SuppressWarnings("unchecked")
public abstract class AbstractPluginDiscovery<T> implements PluginDiscovery<T> {
private static final String PLUGIN_MAPPING_FILE = "plugin-mapping.properties";
/**
* Add jar url to classloader. The different engine should have different logic to add url into
* their own classloader
*/
private static final BiConsumer<ClassLoader, List<URL>> DEFAULT_URL_TO_CLASSLOADER =
(classLoader, urls) -> {
if (classLoader instanceof URLClassLoader) {
urls.forEach(url -> ReflectionUtils.invoke(classLoader, "addURL", url));
} else {
throw new UnsupportedOperationException("can't support custom load jar");
}
};
private final Path pluginDir;
private final Config pluginMappingConfig;
private final BiConsumer<ClassLoader, List<URL>> addURLToClassLoaderConsumer;
protected final ConcurrentHashMap<PluginIdentifier, Optional<List<URL>>> pluginJarPath =
new ConcurrentHashMap<>(Common.COLLECTION_SIZE);
protected final Map<PluginIdentifier, String> sourcePluginInstance;
protected final Map<PluginIdentifier, String> sinkPluginInstance;
protected final Map<PluginIdentifier, String> transformPluginInstance;
public AbstractPluginDiscovery(BiConsumer<ClassLoader, List<URL>> addURLToClassloader) {
this(Common.connectorDir(), loadConnectorPluginConfig(), addURLToClassloader);
}
public AbstractPluginDiscovery() {
this(Common.connectorDir(), loadConnectorPluginConfig());View on GitHub (pinned to cf67b549a7)