pentaho/pentaho-kettle · error · KettlePluginException
PLUGINREGISTRY003
PLUGINREGISTRY003
Error message
Class not found
What it means
At the end of loadClass, the registry loads the class via the plugin's URLClassLoader (ucl.loadClass(className)) and instantiates it. A ClassNotFoundException is rethrown as KettlePluginException 'Class not found' (PLUGINREGISTRY003) with the original as cause — the plugin jar/folder does not contain the mapped class name.
Solutions
- Check the class name in the plugin annotation/plugin.xml against the actual FQN in the jar (javap or jar tf | grep <ClassName>).
- Run jar tf plugin.jar to confirm the class file exists at the expected path.
- Redeploy a complete plugin build; if dependencies are missing, add them to the plugin's lib folder.
- Verify the plugin folder's jars are the version matching the metadata (no stale duplicate jars).
Example fix
// before
@Step(id = "MyStep", classnamelist = {"com.acme.step.MyStepMeta"}) // actual: com.acme.step.MyStepMetaNew
// after
@Step(id = "MyStep", classnamelist = {"com.acme.step.MyStepMetaNew"}) Defensive patterns
Strategy: validation
Validate before calling
String fqn = "com.acme.MyStepMeta";
try {
Class.forName(fqn, false, pluginClassLoader);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Class not in plugin jar: " + fqn);
} Try / catch
try {
Object o = PluginRegistry.getInstance().loadClass(plugin, pluginClass);
} catch (KettlePluginException e) {
if (e.getMessage().contains("Class not found")) {
log.error("Mapped class missing from " + plugin.getName() + " jar; verify plugin.xml/annotation FQNs", e);
}
throw e;
} Prevention
- Run 'jar tf plugin.jar | grep ClassName' before deploying to verify mapped classes exist.
- Add a build-time check that every class in plugin.xml/annotations exists in the artifact.
- Avoid renaming plugin classes without updating metadata in the same commit.
- Place plugin dependencies in the plugin's own lib folder so the URLClassLoader sees them.
When it happens
Trigger: ucl.loadClass(className) fails because the class named in the plugin's metadata (mainClassFolder/classMap entry) is absent from the plugin's jar/folder URLs — wrong class name, missing jar entry, or the jar wasn't added to the classloader.
Common situations: Package/refactor renamed the class but plugin.xml or annotation still lists the old FQN; incomplete plugin deployment (jar missing some classes); dependency classes referenced by the plugin are absent so a NoClassDefFoundError surfaces as lookup failure; class in a nested jar VFS can't open.
Related errors
- PLUGINREGISTRY002
- KettleMissingPluginsException( getErrorMessage(…
- KettleMissingPluginsException( getErrorMessage(…
- No ID specified for plugin with class
- Not a valid id specified in plugin
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/66adec04f163689b.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java:523
throw new KettlePluginClassMapException( BaseMessages.getString( PKG,
"PluginRegistry.RuntimeError.NoValidClassRequested.PLUGINREGISTRY002", plugin.getName(),
pluginClass.getName() ) );
}
try {
Class<? extends T> cl;
if ( plugin.isNativePlugin() ) {
cl = (Class<? extends T>) Class.forName( className );
} else {
ClassLoader ucl = getClassLoader( plugin );
// Load the class.
cl = (Class<? extends T>) ucl.loadClass( className );
}
return cl.newInstance();
} catch ( ClassNotFoundException e ) {
throw new KettlePluginException( BaseMessages.getString(
PKG, "PluginRegistry.RuntimeError.ClassNotFound.PLUGINREGISTRY003" ), e );
} catch ( InstantiationException e ) {
throw new KettlePluginException( BaseMessages.getString(
PKG, "PluginRegistry.RuntimeError.UnableToInstantiateClass.PLUGINREGISTRY004" ), e );
} catch ( IllegalAccessException e ) {
throw new KettlePluginException( BaseMessages.getString(
PKG, "PluginRegistry.RuntimeError.IllegalAccessToClass.PLUGINREGISTRY005" ), e );
} catch ( Throwable e ) {
e.printStackTrace();
throw new KettlePluginException( BaseMessages.getString(
PKG, "PluginRegistry.RuntimeError.UnExpectedErrorLoadingClass.PLUGINREGISTRY007" ), e );
}
}
}
/**
* Add a PluginType to be managed by the registry
*View on GitHub (pinned to f3058517a1)