pentaho/pentaho-kettle · error · KettlePluginException
The 'plugin_id' attribute could not be determined using…
Error message
The 'plugin_id' attribute could not be determined using 'driver_class' value '${driverClassName}' What it means
If plugin_id is empty, the loader tries to infer it by matching the stored driver_class against every registered database plugin's getDriverClass(). When no plugin matches, pluginId remains empty and this KettlePluginException is thrown naming the driver class that could not be mapped.
Solutions
- Correct the driver_class attribute to the exact class name of a registered database plugin
- Set plugin_id directly so no inference is needed
- Install/register a database plugin that supports that driver class
Example fix
// before <attr id="DRIVER_CLASS">com.mysql.jdbc.Driver</attr> // no plugin matches // after <attr id="DRIVER_CLASS">com.mysql.cj.jdbc.Driver</attr> <attr id="PLUGIN_ID">MySQL</attr>
Defensive patterns
Strategy: validation
Validate before calling
PluginRegistry registry = PluginRegistry.getInstance();
boolean matched = registry.getPlugins( DatabasePluginType.class ).stream()
.anyMatch( p -> driverClassName.equalsIgnoreCase(
registry.getDatabase( p ).getDriverClass() ) );
if ( !matched && pluginId.isEmpty() ) throw new IllegalStateException( "No plugin for driver " + driverClassName ); Prevention
- Store plugin_id explicitly rather than relying on driver_class inference
- Keep driver class names in sync with driver version upgrades
- Register third-party database plugins for custom drivers
When it happens
Trigger: Loading an element whose driver_class attribute does not equal any registered database plugin's driver class (pluginId still empty after the registry loop).
Common situations: Driver string from a different vendor/version (e.g. old 'com.mysql.jdbc.Driver' vs new 'com.mysql.cj.jdbc.Driver'); third-party JDBC driver with no corresponding Kettle database plugin; typo in the stored driver class.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- The attributes 'plugin_id' and 'driver_class' can't be both…
- Can not create element type with id…
- Can not create element type with id
- Can't delete element type with name
- Can't encode object of class : className
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/ce7c3fff89c2ddb6.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/metastore/DatabaseMetaStoreUtil.java:207
//
String pluginId = getChildString( element, MetaStoreConst.DB_ATTR_ID_PLUGIN_ID );
String driverClassName = getChildString( element, MetaStoreConst.DB_ATTR_DRIVER_CLASS );
if ( Utils.isEmpty( pluginId ) && Utils.isEmpty( driverClassName ) ) {
throw new KettlePluginException( "The attributes 'plugin_id' and 'driver_class' can't be both empty" );
}
if ( Utils.isEmpty( pluginId ) ) {
// Determine pluginId using the plugin registry.
//
List<PluginInterface> plugins = pluginRegistry.getPlugins( DatabasePluginType.class );
for ( PluginInterface plugin : plugins ) {
DatabaseInterface databaseInterface = (DatabaseInterface) pluginRegistry.loadClass( plugin );
if ( driverClassName.equalsIgnoreCase( databaseInterface.getDriverClass() ) ) {
pluginId = plugin.getIds()[0];
}
}
}
if ( Utils.isEmpty( pluginId ) ) {
throw new KettlePluginException(
"The 'plugin_id' attribute could not be determined using 'driver_class' value '" + driverClassName + "'" );
}
// Look for the plugin
//
PluginInterface plugin = PluginRegistry.getInstance().getPlugin( DatabasePluginType.class, pluginId );
DatabaseInterface databaseInterface = (DatabaseInterface) PluginRegistry.getInstance().loadClass( plugin );
databaseInterface.setPluginId( pluginId );
databaseMeta.setDatabaseInterface( databaseInterface );
databaseMeta.setObjectId( new StringObjectId( element.getId() ) );
databaseMeta.setName( element.getName() );
databaseMeta.setDescription( getChildString( element, MetaStoreConst.DB_ATTR_ID_DESCRIPTION ) );
String accessTypeString = getChildString( element, MetaStoreConst.DB_ATTR_ID_ACCESS_TYPE );
if ( Utils.isEmpty( accessTypeString ) ) {
accessTypeString = DatabaseMeta.getAccessTypeDesc( DatabaseMeta.TYPE_ACCESS_NATIVE );
}View on GitHub (pinned to f3058517a1)