apache/seatunnel · error · FactoryException
Multiple factories for identifier '%s' that implement '%s' f
Error message
Multiple factories for identifier '%s' that implement '%s' found in the classpath. Ambiguous factory classes are: %s
What it means
FactoryUtil.checkMultipleMatchingFactories throws this FactoryException when more than one factory on the classpath claims the same factoryIdentifier for the requested factory interface. Discovery is then ambiguous, so it fails fast and lists the competing classes.
Source
Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/table/factory/FactoryUtil.java:379
+ "%s",
factoryIdentifier,
factoryClass.getName(),
foundFactories.stream()
.map(Factory::factoryIdentifier)
.distinct()
.sorted()
.collect(Collectors.joining("\n"))));
}
checkMultipleMatchingFactories(factoryIdentifier, factoryClass, matchingFactories);
return matchingFactories.get(0);
}
private static <T extends Factory> void checkMultipleMatchingFactories(
String factoryIdentifier, Class<T> factoryClass, List<T> matchingFactories) {
if (matchingFactories.size() > 1) {
throw new FactoryException(
String.format(
"Multiple factories for identifier '%s' that implement '%s' found in the classpath.\n\n"
+ "Ambiguous factory classes are:\n\n"
+ "%s",
factoryIdentifier,
factoryClass.getName(),
matchingFactories.stream()
.map(f -> f.getClass().getName())
.sorted()
.collect(Collectors.joining("\n"))));
}
}
@SuppressWarnings("unchecked")
public static <T extends Factory> List<T> discoverFactories(
ClassLoader classLoader, Class<T> factoryClass) {
return discoverFactories(classLoader).stream()
.filter(f -> factoryClass.isAssignableFrom(f.getClass()))View on GitHub (pinned to cf67b549a7)
Solutions
- List the ambiguous classes in the message and delete the duplicate/outdated jar from the connectors directory.
- Keep only one version of each connector jar in $SEATUNNEL_HOME/connectors/plugin-mapping layout.
- If intentionally overriding a plugin, ensure only one jar with that identifier is visible to the classloader.
Example fix
// before connectors/connector-jdbc-2.3.3.jar connectors/connector-jdbc-2.3.5.jar // after connectors/connector-jdbc-2.3.5.jar # remove the older jar
Defensive patterns
Strategy: validation
Validate before calling
List<Factory> matching = FactoryUtil.discoverFactories(classLoader).stream()
.filter(f -> f.factoryIdentifier().equalsIgnoreCase(pluginId)).collect(Collectors.toList());
if (matching.size() > 1) throw new IllegalStateException("Duplicate plugin jars for identifier: " + pluginId); Try / catch
try {
return FactoryUtil.discoverFactory(cl, TableSourceFactory.class, id);
} catch (FactoryException e) {
throw new IllegalStateException("Remove duplicate connector jars listed in the error", e);
} Prevention
- Keep exactly one jar per connector identifier in the connectors directory.
- Delete old jars after upgrading connectors.
- Avoid copying connector jars into multiple locations visible to the same classloader.
When it happens
Trigger: discoverFactory or discoverOptionalFactory finds 2+ factories whose factoryIdentifier() equals the requested identifier, typically because two different connector jars or two versions of the same connector are on the classpath.
Common situations: Multiple connector jar versions in $SEATUNNEL_HOME/connectors; a custom plugin copied under a different jar name with the same identifier; stale plugins left after an upgrade.
Related errors
- Could not find any factories that implement '%s' in the clas
- Could not find any factories that implement '%s' in the clas
- Unable to create a source for identifier '${factoryIdentifie
- Unable to create a sink for identifier '${factoryIdentifier}
- Could not find any factory for identifier '%s' that implemen
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/b96bd24438000212.
Report an issue: GitHub.