apache/seatunnel · critical · JdbcConnectorException
NO_SUITABLE_DIALECT_FACTORY
NO_SUITABLE_DIALECT_FACTORY
Error message
Could not find any jdbc dialect factories that implement '%s' in the classpath.
What it means
JdbcDialectLoader.load() discovers JDBC dialect factories via Java ServiceLoader; when the discovered factory list is empty it throws this JdbcConnectorException with code NO_SUITABLE_DIALECT_FACTORY. It means no META-INF/services/org.apache.seatunnel...JdbcDialectFactory provider file (and hence no dialect implementation) is present on the thread-context classpath.
Solutions
- Install/deploy the connector-jdbc plugin jars (sh bin/install-plugin.sh <version> or copy the connector-jdbc + target dialect jar into $SEATUNNEL_HOME/connectors)
- Verify META-INF/services/org.apache.seatunnel.connectors.seatunnel.jdbc.internal.dialect.JdbcDialectFactory exists inside the deployed jar
- Check Thread.currentThread().getContextClassLoader() is correct when invoking load() from embedded/custom classloader code
- If building a shaded jar, configure ServiceResourceTransformer so META-INF/services files are merged, not dropped
Example fix
// before: classpath has no jdbc connector jar java -cp app.jar com.example.SeaTunnelJob # -> NO_SUITABLE_DIALECT_FACTORY // after: include connector-jdbc and dialect jars on classpath / plugins dir # copy seatunnel-connectors-v2/connector-jdbc/target/connector-jdbc-*.jar # and the dialect jar (e.g. mysql driver + factory) into $SEATUNNEL_HOME/connectors/ sh bin/install-plugin.sh 2.3.x
Defensive patterns
Strategy: validation
Validate before calling
// before calling load, ensure at least one factory is discoverable
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (!cl.getResources("META-INF/services/org.apache.seatunnel.connectors.seatunnel.jdbc.internal.dialect.JdbcDialectFactory").hasMoreElements()) {
throw new IllegalStateException("connector-jdbc dialect factories not on classpath");
} Try / catch
try {
JdbcDialect dialect = JdbcDialectLoader.load(url, ...);
} catch (JdbcConnectorException e) {
if (e.getCode() == JdbcConnectorErrorCode.NO_SUITABLE_DIALECT_FACTORY) {
log.error("No JDBC dialect factory on classpath; deploy connector-jdbc jars first");
}
throw e;
} Prevention
- Always run sh bin/install-plugin.sh <version> or copy connector-jdbc jars into $SEATUNNEL_HOME/connectors
- Verify jar contains META-INF/services entry for JdbcDialectFactory after custom builds
- Use a shading ServiceResourceTransformer so services files survive fat-jar assembly
- Check Thread.currentThread().getContextClassLoader() when loading dialects from embedded code
When it happens
Trigger: Calling JdbcDialectLoader.load(...) with a context classloader whose classpath contains no JdbcDialectFactory service providers — e.g. connector-jdbc jar(s) not installed, no connector jar deployed to the plugins directory, or a fat/classloader-isolation setup that hides META-INF/services entries.
Common situations: Forgetting to run install-plugin.sh or otherwise not deploying connector-jdbc jars to the Zeta engine's connectors directory; building a minimal distribution without any jdbc dialect module; custom classloader (e.g. inside another framework) that does not expose the service files; shading/assembly plugin stripping META-INF/services.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Can't create JdbcDialect without compatible mode for…
- CLASS_NOT_FOUND
- COMMON-17
- COMMON-19
- CONNECT_FAILED
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/404a5437dc7bab35.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/dialect/JdbcDialectLoader.java:85
* Loads the unique JDBC Dialect that can handle the given database url.
*
* @param url A database URL.
* @param compatibleMode The compatible mode.
* @return The loaded dialect.
* @throws IllegalStateException if the loader cannot find exactly one dialect that can
* unambiguously process the given database URL.
*/
public static JdbcDialect load(
String url,
String compatibleMode,
String dialect,
String fieldIde,
JdbcConnectionConfig jdbcConnectionConfig) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
List<JdbcDialectFactory> foundFactories = discoverFactories(cl);
if (foundFactories.isEmpty()) {
throw new JdbcConnectorException(
JdbcConnectorErrorCode.NO_SUITABLE_DIALECT_FACTORY,
String.format(
"Could not find any jdbc dialect factories that implement '%s' in the classpath.",
JdbcDialectFactory.class.getName()));
}
List<JdbcDialectFactory> matchingFactories;
if (dialect != null) {
matchingFactories =
foundFactories.stream()
.filter(f -> f.dialectFactoryName().equalsIgnoreCase(dialect))
.collect(Collectors.toList());
} else {
matchingFactories =
foundFactories.stream()
.filter(f -> f.acceptsURL(url))
.collect(Collectors.toList());
}
View on GitHub (pinned to cf67b549a7)