pentaho/pentaho-kettle · error · KettlePluginException
PLUGINREGISTRY007
PLUGINREGISTRY007
Error message
Unexpected error loading class:
What it means
PLUGINREGISTRY007 is thrown by PluginRegistry.loadClass when any unexpected Throwable (not ClassNotFoundException, InstantiationException, or IllegalAccessException) escapes while instantiating a plugin class via Class.forName().newInstance(). It is a catch-all in Kettle's plugin registry: the plugin id resolved to a class, but constructing it blew up in an unforeseen way. The original Throwable is chained as the cause and printed to stderr before the KettlePluginException is thrown.
Solutions
- Inspect the chained 'cause' (the stack trace printed to stderr) to identify the real Throwable and fix the underlying class-loading or initialization problem.
- Verify the plugin jar version matches the Kettle/PDI runtime version; redeploy a clean copy of the plugin directory.
- Check for duplicate/conflicting copies of the plugin class on the classpath and remove stale jars from lib/ or the plugin folder.
- If you own the plugin class, move risky work out of the static initializer and constructor so instantiation cannot throw.
- If you are a caller, catch KettlePluginException and fall back to a default implementation or fail fast with a clear message.
Example fix
// before: deployment mixes jar versions plugins/myplugin/myplugin-8.0.jar vs. runtime PDI 9.x // after plugins/myplugin/myplugin-9.2.jar (matching runtime version); inspect printStackTrace() output for the chained cause
Defensive patterns
Strategy: try-catch
Validate before calling
String cls = plugin.getMainClass() != null ? plugin.getMainClass() : className;
if (cls == null || cls.isEmpty()) throw new IllegalStateException("Plugin " + plugin + " has no class to load");
try { Class.forName(cls, false, getClass().getClassLoader()); } catch (Throwable t) { /* resolve before loadClass */ } Type guard
boolean isLoadable(String className) {
try { Class.forName(className, false, getClass().getClassLoader()); return true; }
catch (Throwable t) { return false; }
} Try / catch
try {
T instance = PluginRegistry.getInstance().loadClass(plugin, className, MyInterface.class);
} catch (KettlePluginException e) {
LOG.error("Plugin class instantiation failed (PLUGINREGISTRY007)", e); // inspect e.getCause()
throw new DeploymentException("Bad plugin jar/version: " + plugin, e);
} Prevention
- Keep plugin jar versions aligned with the PDI/Kettle runtime version.
- Avoid throwing from plugin class static initializers and no-arg constructors.
- After upgrading Kettle, redeploy plugin folders from clean builds.
- Always log the chained cause of KettlePluginException, since 007 hides the real Throwable inside it.
When it happens
Trigger: Calling PluginRegistry.loadClass(PluginInterface, Class<T>) or loadClass(pluginId, className, Class<T>) where the target class's static initializer, no-arg constructor, or newInstance() path throws a RuntimeException/Error (e.g. ExceptionInInitializerError, NoSuchMethodError from mismatched jars, ClassFormatError from a corrupted jar), and the plugin's declared class instantiation path is exercised.
Common situations: A plugin jar is compiled against a different Kettle/metadata version than the runtime (NoSuchMethodError/NoClassDefFoundError surfacing as Throwable); a plugin class throws in a static initializer; a corrupted or partially deployed plugin jar; classpath conflicts where two plugin versions shadow each other.
Related errors
- Unexpected error loading class with name
- Error creating class for : + ic[i].getName()
- Error executing UserDefinedJavaClass.getFields():
- PLUGINREGISTRY004
- PLUGINREGISTRY005
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/b16d1f80c917517b.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java:533
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
*
* @param type
*/
public static void addPluginType( PluginTypeInterface type ) {
pluginTypes.add( type );
}
/**
* Added so we can tell when types have been added (but not necessarily registered)
*
* @return the list of added plugin typesView on GitHub (pinned to f3058517a1)