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
- Read the cause: ClassNotFound => add the JAR containing the class or fix effectiveClassName; Linkage/Version errors => fix JAR/Java mismatch
- Ensure all required extra JARs are listed in listDriverExtraJars so dependencies resolve
- Verify the class name matches the driver inside the resolved JAR (unzip -l | grep Driver)
- Re-download/verify the driver JAR if corrupted
- 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
- Verify the class name against the JAR contents (unzip -l)
- Include all driver dependency JARs in the extra-JARs list
- Build/run on a JDK compatible with the driver's class-file version
- Checksum driver JARs after download to catch corruption
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
- Dynamic driver path does not point to a JAR file
- Dynamic driver ' ' does not accept URL: — check the JDBC…
- Dynamic driver ' ' failed to connect to URL
- Dynamic driver ' ' returned null for URL: — check that the…
- Dynamic driver ' ' threw exception checking URL
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)