{"record":{"id":"47e8c64f5c7a3d3b","repo":"pentaho/pentaho-kettle","slug":"pluginregistry008","errorCode":"PLUGINREGISTRY008","errorMessage":"Error creating class loader","messagePattern":"Error creating class loader","errorType":"error_code","errorClass":"KettlePluginException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java","lineNumber":1000,"sourceCode":"                    inverseClassLoaderLookup.computeIfAbsent( ucl, k -> new HashSet<>() ).add( plugin );\n                  }\n                }\n              }\n            }\n          }\n        } finally {\n          lock.writeLock().unlock();\n        }\n\n        // Load the class.\n        return ucl;\n      }\n    } catch ( MalformedURLException e ) {\n      throw new KettlePluginException( BaseMessages.getString(\n          PKG, \"PluginRegistry.RuntimeError.MalformedURL.PLUGINREGISTRY006\" ), e );\n    } catch ( Throwable e ) {\n      e.printStackTrace();\n      throw new KettlePluginException( BaseMessages.getString(\n          PKG, \"PluginRegistry.RuntimeError.UnExpectedCreatingClassLoader.PLUGINREGISTRY008\" ), e );\n    }\n  }\n\n  /**\n   * Allows the tracking of plugins as they come and go.\n   *\n   * @param typeToTrack extension of PluginTypeInterface to track.\n   * @param listener    receives notification when a plugin of the specified type is added/removed/modified\n   * @param <T>         extension of PluginTypeInterface\n   */\n  public <T extends PluginTypeInterface> void addPluginListener( Class<T> typeToTrack, PluginTypeListener listener ) {\n    lock.writeLock().lock();\n    try {\n      Set<PluginTypeListener> list = listeners.computeIfAbsent( typeToTrack, k -> new HashSet<>() );\n      list.add( listener );\n    } finally {\n      lock.writeLock().unlock();","sourceCodeStart":982,"sourceCodeEnd":1018,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java#L982-L1018","documentation":"KettlePluginException with code PLUGINREGISTRY008 thrown by PluginRegistry.createClassLoader as the catch-all for any unexpected Throwable while building the plugin's URLClassLoader. Unlike PLUGINREGISTRY006 it is not limited to MalformedURLException - any error during classloader assembly (e.g. SecurityException, NPE on a null jar path) lands here after being printed to stderr.","triggerScenarios":"Calling PluginRegistry.createClassLoader when anything other than URL parsing fails: a null entry in the jarFiles list, a SecurityManager denying classloader creation, or an unexpected runtime exception while resolving the plugin folder URL.","commonSituations":"Null or empty jar file paths passed programmatically; running under a restrictive security policy or container that forbids new classloaders; corrupted plugin registration metadata producing NPEs; plugin API version mismatch causing registry state surprises.","solutions":["Read the stderr stack trace printed before the exception and the wrapped cause to identify the real failure","Ensure the jarFiles list passed to createClassLoader contains no null entries and the plugin folder is non-null","Check for SecurityManager / container policies blocking ClassLoader creation","Verify plugin metadata (plugin.xml / annotation) is intact for the plugin being loaded"],"exampleFix":"// before\nClassLoader ucl = PluginRegistry.init().createClassLoader(plugin, null); // plugin folder may be null\n// after\nif ( plugin.getPluginDirectory() != null && new File( plugin.getPluginDirectory() ).exists() ) {\n  ClassLoader ucl = PluginRegistry.init().createClassLoader( plugin, null );\n}","handlingStrategy":"try-catch","validationCode":"PluginInterface plugin = ...;\nboolean ok = plugin != null\n  && plugin.getPluginDirectory() != null\n  && new java.io.File( plugin.getPluginDirectory().getPath() ).exists();\nif ( !ok ) throw new IllegalStateException(\"plugin or its folder is not resolvable\");","typeGuard":"static boolean canCreateClassLoader(PluginInterface p) {\n  return p != null && p.getPluginDirectory() != null && p.getJarFiles() != null;\n}","tryCatchPattern":"try {\n  ClassLoader ucl = registry.createClassLoader(plugin, null);\n} catch ( KettlePluginException e ) {\n  if ( e.getMessage().contains(\"PLUGINREGISTRY008\") ) {\n    log.error(\"Unexpected classloader failure for plugin \" + plugin.getName(), e.getCause());\n  }\n}","preventionTips":["Never pass null jarFiles entries to createClassLoader","Run PDI without a restrictive SecurityManager or grant createClassLoader permissions","Validate plugin folders and metadata before initialization","Keep plugin jar layouts conforming to the PDI plugin directory convention (lib/ subdir)"],"tags":["java","classpath","plugin-system"],"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"}