{"record":{"id":"8b54901f3bca6409","repo":"pentaho/pentaho-kettle","slug":"database-exception-unabletofindclassmissingdriver-i18n","errorCode":null,"errorMessage":"Database.Exception.UnableToFindClassMissingDriver (i18n: Unable to find driver class {0} - missing from plugin {1})","messagePattern":"Database\\.Exception\\.UnableToFindClassMissingDriver \\(i18n: Unable to find driver class (.+?) - missing from plugin (.+?)\\)","errorType":"exception","errorClass":"KettleDatabaseException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/database/Database.java","lineNumber":654,"sourceCode":"      throw new KettleDatabaseException( \"Error connecting to database: (using class \" + classname + \")\", e );\n    }\n  }\n\n  private void loadStaticDriver( String classname, PluginInterface plugin ) throws KettleDatabaseException {\n    try {\n      synchronized ( java.sql.DriverManager.class ) {\n        ClassLoader classLoader = PluginRegistry.getInstance().getClassLoader( plugin );\n        Class<?> driverClass = classLoader.loadClass( classname );\n        // Only need DelegatingDriver for drivers not from our classloader\n        if ( driverClass.getClassLoader() != this.getClass().getClassLoader() ) {\n          registerDelegatingDriver( driverClass );\n        } else {\n          // Trigger static register block in driver class\n          Class.forName( classname );\n        }\n      }\n    } catch ( NoClassDefFoundError | ClassNotFoundException e ) {\n      throw new KettleDatabaseException( BaseMessages.getString( PKG,\n        \"Database.Exception.UnableToFindClassMissingDriver\", classname, plugin.getName() ), e );\n    } catch ( Exception e ) {\n      throw new KettleDatabaseException( \"Exception while loading class\", e );\n    }\n  }\n\n  private void registerDelegatingDriver( Class<?> driverClass ) throws KettleDatabaseException {\n    String pluginId =\n      PluginRegistry.getInstance().getPluginId( DatabasePluginType.class, databaseMeta.getDatabaseInterface() );\n    Set<String> registeredDriversFromPlugin = registeredDrivers.computeIfAbsent( pluginId, k -> new HashSet<>() );\n    // Prevent registering multiple delegating drivers for same class, plugin\n    if ( !registeredDriversFromPlugin.contains( driverClass.getCanonicalName() ) ) {\n      try {\n        DriverManager.registerDriver( new DelegatingDriver( (Driver) driverClass.getDeclaredConstructor().newInstance() ) );\n      } catch ( InstantiationException | IllegalAccessException | NoSuchMethodException | java.lang.reflect.InvocationTargetException | SQLException e ) {\n        throw new KettleDatabaseException(\n          \"Unable to register delegating driver for class \" + driverClass.getCanonicalName(), e );\n      }","sourceCodeStart":636,"sourceCodeEnd":672,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/database/Database.java#L636-L672","documentation":"loadStaticDriver throws KettleDatabaseException with i18n key \"Database.Exception.UnableToFindClassMissingDriver\" (\"Unable to find driver class {0} - missing from plugin {1}\") when Class.forName (or the driver's static registration block) raises ClassNotFoundException or NoClassDefFoundError. The driver jar is simply not on the classpath.","triggerScenarios":"Connecting with access type Native/JDBC when the JDBC driver class named in the DatabaseMeta cannot be loaded — driver jar absent from the plugin's lib folder or the application classpath.","commonSituations":"Forgetting to drop the JDBC driver jar into lib/ or the database plugin directory, driver jar excluded from the build (license-based exclusions, e.g. Oracle/MSSQL drivers), fat-jar packaging that omitted the driver.","solutions":["Download the correct JDBC driver and place its jar in the Kettle lib/ or plugins/<db-plugin>/lib directory","Verify the driver class name matches the jar (e.g. org.postgresql.Driver for postgresql-*.jar)","If embedding, ensure the driver is included in the packaged classpath","Restart the application so the dynamic class loader picks up newly added jars"],"exampleFix":"// before\nclasspath: kettle-core.jar, kettle-engine.jar  // no postgres driver\n\n// after\nclasspath: kettle-core.jar, kettle-engine.jar, postgresql-42.7.3.jar","handlingStrategy":"validation","validationCode":"try {\n  Class.forName( driverClassname );\n} catch ( ClassNotFoundException e ) {\n  throw new IllegalStateException( \"JDBC driver \" + driverClassname\n    + \" missing; add the driver jar to lib/ or the plugin's lib directory\" );\n}","typeGuard":"boolean driverPresent = Arrays.stream(\n    System.getProperty( \"java.class.path\" ).split( File.pathSeparator ) )\n  .noneMatch( p -> p.contains( \"missing-driver\" ) ); // or scan for expected jar name","tryCatchPattern":"try {\n  db.connect();\n} catch ( KettleDatabaseException e ) {\n  if ( e.getMessage().contains( \"missing from plugin\" ) ) {\n    log.error( \"Install the JDBC driver jar named in the message into lib/\" );\n  }\n}","preventionTips":["Ship the JDBC driver jar with every deployment (check license terms)","Verify driver presence at application startup with Class.forName","Document required driver jars per database type in deployment runbooks"],"tags":["class-not-found","jdbc-driver","missing-dependency"],"backgroundTag":"class-not-found","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}