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

  1. 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)
  2. Verify META-INF/services/org.apache.seatunnel.connectors.seatunnel.jdbc.internal.dialect.JdbcDialectFactory exists inside the deployed jar
  3. Check Thread.currentThread().getContextClassLoader() is correct when invoking load() from embedded/custom classloader code
  4. 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

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


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)