pentaho/pentaho-kettle · error · KettleDatabaseException

Database.Exception.UnableToFindClassMissingDriver

Error message

Database.Exception.UnableToFindClassMissingDriver (i18n: Unable to find driver class {0} - missing from plugin {1})

What it means

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.

Solutions

  1. Download the correct JDBC driver and place its jar in the Kettle lib/ or plugins/<db-plugin>/lib directory
  2. Verify the driver class name matches the jar (e.g. org.postgresql.Driver for postgresql-*.jar)
  3. If embedding, ensure the driver is included in the packaged classpath
  4. Restart the application so the dynamic class loader picks up newly added jars

Example fix

// before
classpath: kettle-core.jar, kettle-engine.jar  // no postgres driver

// after
classpath: kettle-core.jar, kettle-engine.jar, postgresql-42.7.3.jar
Defensive patterns

Strategy: validation

Validate before calling

try {
  Class.forName( driverClassname );
} catch ( ClassNotFoundException e ) {
  throw new IllegalStateException( "JDBC driver " + driverClassname
    + " missing; add the driver jar to lib/ or the plugin's lib directory" );
}

Type guard

boolean driverPresent = Arrays.stream(
    System.getProperty( "java.class.path" ).split( File.pathSeparator ) )
  .noneMatch( p -> p.contains( "missing-driver" ) ); // or scan for expected jar name

Try / catch

try {
  db.connect();
} catch ( KettleDatabaseException e ) {
  if ( e.getMessage().contains( "missing from plugin" ) ) {
    log.error( "Install the JDBC driver jar named in the message into lib/" );
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

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

      throw new KettleDatabaseException( "Error connecting to database: (using class " + classname + ")", e );
    }
  }

  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 );
      }

View on GitHub (pinned to f3058517a1)