apache/seatunnel · warning
plugin dir: {} not exists, load plugin from classpath
Error message
plugin dir: {} not exists, load plugin from classpath What it means
getPluginFactories expects the configured plugin directory (e.g., connectors/) to exist so it can build a URLClassLoader over its jars. If the directory does not exist, it logs this warning and instead discovers factories from the thread context classpath, which usually contains only core classes — typically leading to 'plugin not found' errors later.
Source
Thrown at seatunnel-plugin-discovery/src/main/java/org/apache/seatunnel/plugin/discovery/AbstractPluginDiscovery.java:385
}
protected List<Factory> getPluginFactories() {
List<Factory> factories;
if (this.pluginDir.toFile().exists()) {
log.debug("load plugin from plugin dir: {}", this.pluginDir);
List<URL> files;
try {
files = FileUtils.searchJarFiles(this.pluginDir);
} catch (IOException e) {
throw new RuntimeException(
String.format(
"Can not find any plugin(source/sink/transform) in the dir: %s",
this.pluginDir));
}
factories =
FactoryUtil.discoverFactories(new URLClassLoader(files.toArray(new URL[0])));
} else {
log.warn("plugin dir: {} not exists, load plugin from classpath", this.pluginDir);
factories =
FactoryUtil.discoverFactories(Thread.currentThread().getContextClassLoader());
}
return factories;
}
protected T loadPluginInstance(PluginIdentifier pluginIdentifier, ClassLoader classLoader) {
ServiceLoader<T> serviceLoader = ServiceLoader.load(getPluginBaseClass(), classLoader);
for (T t : serviceLoader) {
if (t instanceof PluginIdentifierInterface) {
// new api
PluginIdentifierInterface pluginIdentifierInstance = (PluginIdentifierInterface) t;
if (StringUtils.equalsIgnoreCase(
pluginIdentifierInstance.getPluginName(),
pluginIdentifier.getPluginName())) {
return (T) pluginIdentifierInstance;
}
} else {View on GitHub (pinned to cf67b549a7)
Solutions
- Set SEATUNNEL_HOME correctly on every node so the connectors/ dir resolves
- Run sh bin/install-plugin.sh <version> to download connector jars into the plugin dir
- If you intentionally ship connectors on the classpath, confirm the connector jar is inside lib/ or the app classpath
- Verify the plugin dir path in your config/CLI (e.g., --name uses correct connector identifier once dir exists)
Example fix
// before: missing dir export SEATUNNEL_HOME=/opt/seatunnel # connectors/ absent // after sh bin/install-plugin.sh 2.3.x ls $SEATUNNEL_HOME/connectors/connector-console-*.jar
Defensive patterns
Strategy: validation
Validate before calling
File pluginDir = new File(System.getenv("SEATUNNEL_HOME"), "connectors");
if (!pluginDir.isDirectory()) throw new IllegalStateException("install connectors: " + pluginDir); Prevention
- Set SEATUNNEL_HOME on every cluster node
- Run install-plugin.sh before first job
- Keep connector jars on classpath if running plugin-less
- Check dir path after upgrades/migrations
When it happens
Trigger: The pluginDir passed to AbstractPluginDiscovery (derived from SEATUNNEL_HOME/connectors or a -Dplugin config) does not exist on the node starting the job.
Common situations: SEATUNNEL_HOME not set or wrong on a cluster node; connector never installed (install-plugin.sh not run); running from IDE/source without connectors dir; fat-jar deployment without plugin dirs.
Related errors
- Plugin %s not found.
- CONFIG_VALIDATION_FAILED
- can't support custom load jar
- Can not find any plugin(source/sink/transform) in the dir: %
- Cannot find unique plugin jar for pluginIdentifier: %s -> %s
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/febafcb9f13c68fe.
Report an issue: GitHub.