pentaho/pentaho-kettle · error · KettleDatabaseException

Dynamic driver: failed to load

Error message

Dynamic driver: failed to load '{effectiveClassName}' from '{resolvedPath}': {message}

What it means

Thrown when the URLClassLoader built from the resolved JAR cannot load/instantiate the driver class named effectiveClassName. The original exception (ClassNotFound, LinkageError, instantiation failure, etc.) is preserved as the cause and its message is embedded. The classloader is closed before throwing.

Solutions

  1. Read the cause: ClassNotFound => add the JAR containing the class or fix effectiveClassName; Linkage/Version errors => fix JAR/Java mismatch
  2. Ensure all required extra JARs are listed in listDriverExtraJars so dependencies resolve
  3. Verify the class name matches the driver inside the resolved JAR (unzip -l | grep Driver)
  4. Re-download/verify the driver JAR if corrupted
  5. Use the driver version matching your database server

Example fix

// before
loadDynamicDriver("postgres", "org.postgresql.Driver9", jars); // class doesn't exist in JAR
// after
loadDynamicDriver("postgres", "org.postgresql.Driver", jars);
Defensive patterns

Strategy: validation

Validate before calling

try (URLClassLoader l = new URLClassLoader(new URL[]{ new File(jarPath).toURI().toURL() }, getClass().getClassLoader())) {
  Class<?> c = l.loadClass(effectiveClassName);
  if (!java.sql.Driver.class.isAssignableFrom(c)) throw new IllegalStateException(effectiveClassName + " is not a Driver in " + jarPath);
}

Try / catch

try { db.connect(); } catch (KettleDatabaseException e) { if (e.getMessage().startsWith("Dynamic driver: failed to load")) { log.error("Driver load failed: " + e.getCause(), e); } else throw e; }

Prevention

When it happens

Trigger: connectUsingClass -> loadDynamicDriver: the resolved JAR exists and is a .jar, but Class.forName/newInstance inside the loader fails — class not present in that JAR, missing transitive dependency classes, wrong class name from the database plugin metadata, or conflicting class versions.

Common situations: effectiveClassName typo'd or from a different driver major version; driver JAR missing its dependency JARs (which should come via resolveAll of listDriverExtraJars); fat-thin driver mixup; JAR corrupted or built for a different Java version (UnsupportedClassVersionError).

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/80b56d48b9c60be8. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/database/Database.java:925

    } else {
      // No-cache path: fresh classloader and Driver per connection; closed on disconnect().
      List<URL> urls = JdbcDriverResolver.buildUrlList( resolvedPath, extraJarPaths );
      ChildFirstURLClassLoader loader = null;
      try {
        loader = new ChildFirstURLClassLoader( urls.toArray( new URL[ 0 ] ), Database.class.getClassLoader() );
        Class<?> driverClass = loader.loadClass( effectiveClassName );
        Driver driver = (Driver) driverClass.getDeclaredConstructor().newInstance();
        dynamicDriver.set( driver );
        dynamicDriverClassLoader.set( loader );
      } catch ( Exception e ) {
        if ( loader != null ) {
          try {
            loader.close();
          } catch ( Exception ignored ) {
            // best-effort
          }
        }
        throw new KettleDatabaseException(
          "Dynamic driver: failed to load '" + effectiveClassName + "' from '" + resolvedPath + "': " + e.getMessage(), e );
      }
    }
  }

  /**
   * Opens a JDBC connection via the already-loaded {@link #dynamicDriver}, bypassing
   * {@link DriverManager}. Validates URL acceptance before connecting.
   */
  private Connection openConnectionViaDynamicDriver( String effectiveClassName, String url, Properties properties )
    throws KettleDatabaseException {
    Driver localDriver = dynamicDriver.get();
    if ( localDriver == null ) {
      throw new KettleDatabaseException(
        "Dynamic driver for '" + effectiveClassName + "' has been unloaded (disconnect was called concurrently). "
          + "Reconnect to reload the driver." );
    }
    boolean accepts;

View on GitHub (pinned to f3058517a1)