pentaho/pentaho-kettle · error · RuntimeException
Error creating plugin class
Error message
Error creating plugin class
What it means
SupplementalPlugin.loadClass resolves a registered supplier/callable for the plugin class and invokes it to produce the plugin instance; any exception during that factory call is wrapped as RuntimeException containing a KettlePluginException 'Error creating plugin class'. It signals the plugin's factory (usually a no-arg constructor or lambda registered in factoryMap) failed.
Solutions
- Read the wrapped KettlePluginException cause to see why the plugin's constructor/factory failed
- Initialize the Kettle environment (KettleEnvironment.init()) before loading supplemental plugins
- Ensure the plugin class has a public no-arg constructor and all its dependencies are on the classpath
- Unwrap the RuntimeException: new KettlePluginException(...) is the cause, and its cause is the original failure
Example fix
// before MyStepPlugin plugin = supplementalPlugin.loadClass(); // env not initialized // after KettleEnvironment.init(); MyStepPlugin plugin = supplementalPlugin.loadClass();
Defensive patterns
Strategy: try-catch
Validate before calling
KettleEnvironment.init(); // ensure environment is ready before loadClass Object factory = supplementalPlugin.getClass() != null; // plugin class resolvable Class.forName(pluginClassName);
Type guard
static boolean canInstantiate(String cls) {
try { Class.forName(cls).getConstructor().newInstance(); return true; }
catch ( Exception e ) { return false; }
} Try / catch
try {
T plugin = supplementalPlugin.loadClass();
} catch ( RuntimeException e ) {
// cause is KettlePluginException, whose cause is the factory failure
Throwable root = e.getCause() != null ? e.getCause().getCause() : e;
log.error("Supplemental plugin factory failed", root);
} Prevention
- Call KettleEnvironment.init() before any plugin loading
- Give supplemental plugin classes a public no-arg constructor
- Keep factory registrations in sync with plugin class changes across versions
- Smoke-test plugin loading at deployment time, not first use
When it happens
Trigger: Calling SupplementalPlugin.loadClass() when the Callable registered in factoryMap for pluginClass throws - typically the plugin class's constructor throws, or no mapping exists and the code path assumes one (resulting in NPE wrapped here).
Common situations: Supplemental plugin's constructor depends on an uninitialized Kettle environment (e.g. KettleLogStore or properties not initialized yet); plugin class changed between versions so the registered factory no longer matches; plugin class throws due to missing dependencies on the classpath.
Related errors
- Unable to get instance of plugin type
- Clone not supported for
- PLUGINREGISTRY006
- PLUGINREGISTRY008
- A server socket allocation always has to accompanied by a…
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/8d5afbb7c62d1de8.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/plugins/SupplementalPlugin.java:50
private String id;
public SupplementalPlugin( Class<? extends PluginTypeInterface> pluginClass, String id ) {
super( new String[] { id }, pluginClass, null,
"", id, id, "", false, false, Collections.emptyMap(), Collections.emptyList(), "",
null );
this.pluginClass = pluginClass;
this.id = id;
}
@Override public <T> T loadClass( Class<T> pluginClass ) {
if ( !factoryMap.containsKey( pluginClass ) ) {
return null;
}
try {
return (T) factoryMap.get( pluginClass ).call();
} catch ( Exception e ) {
throw new RuntimeException( new KettlePluginException( "Error creating plugin class", e ) );
}
}
@Override public ClassLoader getClassLoader() {
return getClass().getClassLoader();
}
public <T> void addFactory( Class<T> tClass, Callable<T> callable ) {
factoryMap.put( tClass, callable );
}
}
View on GitHub (pinned to f3058517a1)