pentaho/pentaho-kettle · error · KettlePluginException
PLUGINREGISTRY001
PLUGINREGISTRY001
Error message
Not a valid plugin
What it means
PluginRegistry.loadClass instantiates the class for a given plugin. The first guard rejects a null PluginInterface argument with message 'Not a valid plugin' (localized key PluginRegistry.RuntimeError.NoValidStepOrPlugin.PLUGINREGISTRY001). It means the caller passed no plugin at all, so there is nothing to load a class from.
Solutions
- Check the return of registry.findPluginWithId/findPluginByName for null before calling loadClass.
- Verify the plugin id used in the lookup matches the registered id exactly (case-sensitive).
- Confirm the plugin actually registered: check startup logs for plugin registration errors (e.g. error 300/303) that left it unregistered.
- Ensure the plugin folder containing the jar is in the scanned plugin folders list.
Example fix
// before
PluginInterface plugin = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, stepId);
Object obj = PluginRegistry.getInstance().loadClass(plugin, StepMetaInterface.class); // NPE risk
// after
PluginInterface plugin = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, stepId);
if (plugin == null) {
throw new KettleException("Step plugin not registered for id: " + stepId);
}
Object obj = PluginRegistry.getInstance().loadClass(plugin, StepMetaInterface.class); Defensive patterns
Strategy: type-guard
Validate before calling
PluginInterface plugin = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, stepId);
if (plugin == null) {
throw new KettleException("No plugin registered for id '" + stepId + "'");
} Type guard
static PluginInterface requirePlugin(PluginRegistry reg, Class<? extends PluginTypeInterface> type, String id) {
PluginInterface p = reg.findPluginWithId(type, id);
if (p == null) throw new KettleException("Plugin not registered: " + id);
return p;
} Try / catch
try {
Object o = PluginRegistry.getInstance().loadClass(plugin, StepMetaInterface.class);
} catch (KettlePluginException e) {
if (plugin == null || e.getMessage().contains("Not a valid plugin")) {
throw new KettleException("Plugin lookup failed before loadClass; id not registered", e);
}
} Prevention
- Never call loadClass without null-checking the plugin from findPluginWithId/findPluginByName.
- Spell-check plugin ids; they are case-sensitive.
- Check startup logs for registration failures that leave plugins unregistered.
- Verify plugin folders are scanned (KETTLE_PLUGIN_FOLDERS) before lookups.
When it happens
Trigger: loadClass(plugin, pluginClass) is called with plugin == null — e.g. findPluginWithId/findPluginByName returned null because the plugin isn't registered, and the return value was passed straight into loadClass without a null check.
Common situations: A step/job-entry id is misspelled so registry lookup returns null; a plugin failed to register at startup (e.g. due to missing ID or bad jar) so lookups return null; plugin folder not scanned; callers like JobEntryCopy loading the job entry class after a null lookup.
Related errors
- Not a valid id specified in plugin
- PLUGINREGISTRY002
- KettleMissingPluginsException( getErrorMessage(…
- KettleMissingPluginsException( getErrorMessage(…
- No ID specified for plugin with class
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/83b3aec56a9d8589.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java:478
supplementalPlugin.addFactory( tClass, callable );
}
private String createSupplemantalKey( String pluginName, String id ) {
return pluginName + "-" + id + SUPPLEMENTALS_SUFFIX;
}
/**
* Load and instantiate the plugin class specified
*
* @param plugin the plugin to load
* @param pluginClass the class to be loaded
* @return The instantiated class
* @throws KettlePluginException In case there was a class loading problem somehow
*/
@SuppressWarnings( "unchecked" )
public <T> T loadClass( PluginInterface plugin, Class<T> pluginClass ) throws KettlePluginException {
if ( plugin == null ) {
throw new KettlePluginException( BaseMessages.getString(
PKG, "PluginRegistry.RuntimeError.NoValidStepOrPlugin.PLUGINREGISTRY001" ) );
}
if ( plugin instanceof ClassLoadingPluginInterface ) {
T aClass = ( (ClassLoadingPluginInterface) plugin ).loadClass( pluginClass );
if ( aClass == null ) {
throw new KettlePluginClassMapException( BaseMessages
.getString( PKG, "PluginRegistry.RuntimeError.NoValidClassRequested.PLUGINREGISTRY002", plugin.getName(),
pluginClass.getName() ) );
} else {
return aClass;
}
} else {
String className = plugin.getClassMap().get( pluginClass );
if ( className == null ) {
// Look for supplemental plugin supplying extra classes
for ( String id : plugin.getIds() ) {
try {View on GitHub (pinned to f3058517a1)