{"record":{"id":"8d5afbb7c62d1de8","repo":"pentaho/pentaho-kettle","slug":"error-creating-plugin-class","errorCode":null,"errorMessage":"Error creating plugin class","messagePattern":"Error creating plugin class","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/plugins/SupplementalPlugin.java","lineNumber":50,"sourceCode":"  private String id;\n\n  public SupplementalPlugin( Class<? extends PluginTypeInterface> pluginClass, String id ) {\n    super( new String[] { id }, pluginClass, null,\n      \"\", id, id, \"\", false, false, Collections.emptyMap(), Collections.emptyList(), \"\",\n      null );\n    this.pluginClass = pluginClass;\n    this.id = id;\n  }\n\n  @Override public <T> T loadClass( Class<T> pluginClass ) {\n    if ( !factoryMap.containsKey( pluginClass ) ) {\n      return null;\n    }\n\n    try {\n      return (T) factoryMap.get( pluginClass ).call();\n    } catch ( Exception e ) {\n      throw new RuntimeException( new KettlePluginException( \"Error creating plugin class\", e ) );\n    }\n  }\n\n  @Override public ClassLoader getClassLoader() {\n    return getClass().getClassLoader();\n  }\n\n  public <T> void addFactory( Class<T> tClass, Callable<T> callable ) {\n    factoryMap.put( tClass, callable );\n  }\n\n}\n","sourceCodeStart":32,"sourceCodeEnd":63,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/plugins/SupplementalPlugin.java#L32-L63","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nMyStepPlugin plugin = supplementalPlugin.loadClass(); // env not initialized\n// after\nKettleEnvironment.init();\nMyStepPlugin plugin = supplementalPlugin.loadClass();","handlingStrategy":"try-catch","validationCode":"KettleEnvironment.init(); // ensure environment is ready before loadClass\nObject factory = supplementalPlugin.getClass() != null; // plugin class resolvable\nClass.forName(pluginClassName);","typeGuard":"static boolean canInstantiate(String cls) {\n  try { Class.forName(cls).getConstructor().newInstance(); return true; }\n  catch ( Exception e ) { return false; }\n}","tryCatchPattern":"try {\n  T plugin = supplementalPlugin.loadClass();\n} catch ( RuntimeException e ) {\n  // cause is KettlePluginException, whose cause is the factory failure\n  Throwable root = e.getCause() != null ? e.getCause().getCause() : e;\n  log.error(\"Supplemental plugin factory failed\", root);\n}","preventionTips":["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"],"tags":["java","plugin-system","reflection"],"backgroundTag":"module-init-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}