pentaho/pentaho-kettle · error · KettleDatabaseException
Exception while loading class
Error message
Exception while loading class
What it means
loadStaticDriver's final catch (Exception) wraps any unexpected error during driver class loading/registration (other than ClassNotFoundException/NoClassDefFoundError) into KettleDatabaseException("Exception while loading class"). Typically this is a linkage or initialization error inside the driver class's static initializer.
Solutions
- Inspect the wrapped cause — ExceptionInInitializerError exposes the static-init failure via getCause()
- Replace the driver jar with a fresh, compatible download
- Resolve conflicting dependency versions on the classpath
- Run with -verbose:class to confirm the class is loaded from the expected jar location
Example fix
// before // conflicting protobuf jars on classpath -> static init fails lib/protobuf-java-2.5.0.jar lib/protobuf-java-3.19.0.jar // after lib/protobuf-java-3.19.0.jar // single version matching driver requirement
Defensive patterns
Strategy: try-catch
Validate before calling
try {
Class.forName( driverClassname, true, loader );
} catch ( Throwable t ) {
log.error( "Driver failed static initialization: " + t.getCause(), t );
} Try / catch
try {
db.connect();
} catch ( KettleDatabaseException e ) {
if ( "Exception while loading class".equals( e.getMessage() ) ) {
Throwable initFailure = e.getCause() != null ? e.getCause().getCause() : null;
log.error( "Driver init problem: " + initFailure, initFailure );
}
} Prevention
- Deduplicate dependency versions that drivers rely on (e.g. protobuf, guava)
- Verify jar integrity (checksums) after download/transfer
- Load drivers once at startup to surface init errors early
- Keep JVM version aligned with driver requirements
When it happens
Trigger: ExceptionInInitializerError-like conditions or other RuntimeExceptions thrown when Class.forName triggers the driver's static registration block — corrupted jars, incompatible dependency versions, or static init that depends on missing system properties.
Common situations: Driver jar built for a different JVM/dependency version, partially downloaded/corrupted jar, conflicting versions of a shared dependency (e.g. protobuf vs newer drivers), security policy blocking class definition.
Related errors
- Error connecting to database
- Database.Exception.UnableToGetMetadata
- DynamicDriverCache: failed to load driver '" +…
- JdbcDriverResolver: driver JAR '" + driverId + ".jar" + "'…
- JdbcDriverResolver: driverId must not be null or blank
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/7b03010c656379b2.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/database/Database.java:657
private void loadStaticDriver( String classname, PluginInterface plugin ) throws KettleDatabaseException {
try {
synchronized ( java.sql.DriverManager.class ) {
ClassLoader classLoader = PluginRegistry.getInstance().getClassLoader( plugin );
Class<?> driverClass = classLoader.loadClass( classname );
// Only need DelegatingDriver for drivers not from our classloader
if ( driverClass.getClassLoader() != this.getClass().getClassLoader() ) {
registerDelegatingDriver( driverClass );
} else {
// Trigger static register block in driver class
Class.forName( classname );
}
}
} catch ( NoClassDefFoundError | ClassNotFoundException e ) {
throw new KettleDatabaseException( BaseMessages.getString( PKG,
"Database.Exception.UnableToFindClassMissingDriver", classname, plugin.getName() ), e );
} catch ( Exception e ) {
throw new KettleDatabaseException( "Exception while loading class", e );
}
}
private void registerDelegatingDriver( Class<?> driverClass ) throws KettleDatabaseException {
String pluginId =
PluginRegistry.getInstance().getPluginId( DatabasePluginType.class, databaseMeta.getDatabaseInterface() );
Set<String> registeredDriversFromPlugin = registeredDrivers.computeIfAbsent( pluginId, k -> new HashSet<>() );
// Prevent registering multiple delegating drivers for same class, plugin
if ( !registeredDriversFromPlugin.contains( driverClass.getCanonicalName() ) ) {
try {
DriverManager.registerDriver( new DelegatingDriver( (Driver) driverClass.getDeclaredConstructor().newInstance() ) );
} catch ( InstantiationException | IllegalAccessException | NoSuchMethodException | java.lang.reflect.InvocationTargetException | SQLException e ) {
throw new KettleDatabaseException(
"Unable to register delegating driver for class " + driverClass.getCanonicalName(), e );
}
registeredDriversFromPlugin.add( driverClass.getCanonicalName() );
}
}View on GitHub (pinned to f3058517a1)