apache/seatunnel · error · RuntimeException
Unsupported classloader:
Error message
Unsupported classloader:
What it means
ConfigValidationUtils installs an ADD_URL_TO_CLASSLOADER consumer that reflectively calls URLClassLoader.addURL to inject plugin jars. If the classloader is not a URLClassLoader (or the reflective add fails), it wraps the failure in RuntimeException('Unsupported classloader: <className>').
Solutions
- Ensure validation runs with a URLClassLoader as the context classloader
- Wrap the target classloader in a new URLClassLoader(urls, parent) before validation
- Check the exception cause; if the reflective addURL itself failed, align JDK version/permissions
Example fix
// before ClassLoader cl = Thread.currentThread().getContextClassLoader(); // custom loader // after ClassLoader parent = Thread.currentThread().getContextClassLoader(); URLClassLoader cl = new URLClassLoader(urls, parent); // ensure URLClassLoader is used
Defensive patterns
Strategy: try-catch
Validate before calling
if (!(Thread.currentThread().getContextClassLoader() instanceof URLClassLoader)) { /* wrap in new URLClassLoader(urls, parent) */ } Type guard
boolean isUrlClassLoader(ClassLoader cl) { return cl instanceof URLClassLoader; } Try / catch
try { ConfigValidationUtils.validate(config); } catch (RuntimeException e) { if (e.getMessage().startsWith("Unsupported classloader")) { /* re-run with URLClassLoader */ } } Prevention
- Run validation with a plain URLClassLoader as context classloader
- Avoid embedding validation under application servers with custom loaders
- Wrap external classloaders before plugin discovery
When it happens
Trigger: Plugin discovery runs with a classloader that is not a URLClassLoader, e.g. when running inside a container/agent that supplies a custom (AppCDS, Spring Boot LaunchedURLClassLoader variants, module) classloader.
Common situations: Embedding SeaTunnel validation in another application server, unusual -Djava.system.class.loader settings, or running under tooling that replaces the context classloader.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unsupported classloader
- can't load jar use current thread classloader, use…
- CONFIG_VALIDATION_FAILED
- CREATE_DRIVER_FAILED
- Failed to call factoryIdentifier method.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/1afbfe8d74391015.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-core/seatunnel-core-starter/src/main/java/org/apache/seatunnel/core/starter/utils/ConfigValidationUtils.java:101
private static final BiConsumer<ClassLoader, List<URL>> ADD_URL_TO_CLASSLOADER =
(classLoader, urls) -> {
if (classLoader instanceof URLClassLoader) {
urls.forEach(url -> ReflectionUtils.invoke(classLoader, "addURL", url));
} else {
try {
Optional<Method> method =
ReflectionUtils.getDeclaredMethod(
URLClassLoader.class, "addURL", URL.class);
if (!method.isPresent()) {
throw new IllegalStateException(
"Unable to find addURL method from URLClassLoader");
}
method.get().setAccessible(true);
for (URL url : urls) {
method.get().invoke(classLoader, url);
}
} catch (Exception e) {
throw new RuntimeException(
"Unsupported classloader: " + classLoader.getClass().getName(), e);
}
}
};
private ConfigValidationUtils() {}
public static void validate(Config config) {
validate(config, CheckResult.success());
}
public static void validate(Config config, CheckResult checkResult) {
if (!checkResult.isSuccess()) {
throw new ConfigCheckException(checkResult.getMsg());
}
ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader validationClassLoader = prepareClassLoader(config, parentClassLoader);View on GitHub (pinned to cf67b549a7)