pentaho/pentaho-kettle · error · KettlePluginException

The attributes 'plugin_id' and 'driver_class' can't be both…

Error message

The attributes 'plugin_id' and 'driver_class' can't be both empty

What it means

loadDatabaseMetaFromDatabaseElement() reconstructs a DatabaseMeta from a stored element. It needs at least one of the plugin_id (DB_ATTR_ID_PLUGIN_ID) or driver_class attributes to identify which database plugin to instantiate. If both are empty it throws KettlePluginException because the plugin cannot be determined.

Solutions

  1. Add a valid plugin_id attribute (e.g. 'MySQL', 'POSTGRESQL') to the stored element
  2. Set the driver_class attribute (e.g. 'com.mysql.cj.jdbc.Driver') so pluginId can be derived via the registry
  3. Re-save the connection from the UI/SDK so all required attributes are written

Example fix

// before
element without DB_ATTR_ID_PLUGIN_ID or DB_ATTR_DRIVER_CLASS
// after
element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_PLUGIN_ID, "POSTGRESQL" ) );
Defensive patterns

Strategy: validation

Validate before calling

String pluginId = DatabaseMetaStoreUtil.getChildString( element, MetaStoreConst.DB_ATTR_ID_PLUGIN_ID );
String driver = DatabaseMetaStoreUtil.getChildString( element, MetaStoreConst.DB_ATTR_DRIVER_CLASS );
if ( ( pluginId == null || pluginId.isEmpty() ) && ( driver == null || driver.isEmpty() ) ) {
  throw new IllegalStateException( "Element needs plugin_id or driver_class" );
}

Prevention

When it happens

Trigger: Loading a stored database element that was written without the plugin_id attribute and without a driver_class attribute.

Common situations: Metastore element created by hand or by a third-party tool; attributes dropped during migration; older export format missing these fields.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/metastore/DatabaseMetaStoreUtil.java:193

    try {
      element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_JDBC_URL, databaseMeta.getURL() ) );
    } catch ( Exception e ) {
      throw new MetaStoreException( "Unable to assemble URL from database '" + databaseMeta.getName() + "'", e );
    }

    return element;
  }

  public static DatabaseMeta loadDatabaseMetaFromDatabaseElement( IMetaStore metaStore, IMetaStoreElement element ) throws KettlePluginException {
    DatabaseMeta databaseMeta = new DatabaseMeta();
    PluginRegistry pluginRegistry = PluginRegistry.getInstance();

    // Load the appropriate database plugin (database interface)
    //
    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

View on GitHub (pinned to f3058517a1)