{"record":{"id":"83b3aec56a9d8589","repo":"pentaho/pentaho-kettle","slug":"pluginregistry001","errorCode":"PLUGINREGISTRY001","errorMessage":"Not a valid plugin","messagePattern":"Not a valid plugin","errorType":"error_code","errorClass":"KettlePluginException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java","lineNumber":478,"sourceCode":"    supplementalPlugin.addFactory( tClass, callable );\n  }\n\n  private String createSupplemantalKey( String pluginName, String id ) {\n    return pluginName + \"-\" + id + SUPPLEMENTALS_SUFFIX;\n  }\n\n  /**\n   * Load and instantiate the plugin class specified\n   *\n   * @param plugin      the plugin to load\n   * @param pluginClass the class to be loaded\n   * @return The instantiated class\n   * @throws KettlePluginException In case there was a class loading problem somehow\n   */\n  @SuppressWarnings( \"unchecked\" )\n  public <T> T loadClass( PluginInterface plugin, Class<T> pluginClass ) throws KettlePluginException {\n    if ( plugin == null ) {\n      throw new KettlePluginException( BaseMessages.getString(\n          PKG, \"PluginRegistry.RuntimeError.NoValidStepOrPlugin.PLUGINREGISTRY001\" ) );\n    }\n\n    if ( plugin instanceof ClassLoadingPluginInterface ) {\n      T aClass = ( (ClassLoadingPluginInterface) plugin ).loadClass( pluginClass );\n      if ( aClass == null ) {\n        throw new KettlePluginClassMapException( BaseMessages\n            .getString( PKG, \"PluginRegistry.RuntimeError.NoValidClassRequested.PLUGINREGISTRY002\", plugin.getName(),\n                pluginClass.getName() ) );\n      } else {\n        return aClass;\n      }\n    } else {\n      String className = plugin.getClassMap().get( pluginClass );\n      if ( className == null ) {\n        // Look for supplemental plugin supplying extra classes\n        for ( String id : plugin.getIds() ) {\n          try {","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java#L460-L496","documentation":"PluginRegistry.loadClass instantiates the class for a given plugin. The first guard rejects a null PluginInterface argument with message 'Not a valid plugin' (localized key PluginRegistry.RuntimeError.NoValidStepOrPlugin.PLUGINREGISTRY001). It means the caller passed no plugin at all, so there is nothing to load a class from.","triggerScenarios":"loadClass(plugin, pluginClass) is called with plugin == null — e.g. findPluginWithId/findPluginByName returned null because the plugin isn't registered, and the return value was passed straight into loadClass without a null check.","commonSituations":"A step/job-entry id is misspelled so registry lookup returns null; a plugin failed to register at startup (e.g. due to missing ID or bad jar) so lookups return null; plugin folder not scanned; callers like JobEntryCopy loading the job entry class after a null lookup.","solutions":["Check the return of registry.findPluginWithId/findPluginByName for null before calling loadClass.","Verify the plugin id used in the lookup matches the registered id exactly (case-sensitive).","Confirm the plugin actually registered: check startup logs for plugin registration errors (e.g. error 300/303) that left it unregistered.","Ensure the plugin folder containing the jar is in the scanned plugin folders list."],"exampleFix":"// before\nPluginInterface plugin = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, stepId);\nObject obj = PluginRegistry.getInstance().loadClass(plugin, StepMetaInterface.class); // NPE risk\n\n// after\nPluginInterface plugin = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, stepId);\nif (plugin == null) {\n  throw new KettleException(\"Step plugin not registered for id: \" + stepId);\n}\nObject obj = PluginRegistry.getInstance().loadClass(plugin, StepMetaInterface.class);","handlingStrategy":"type-guard","validationCode":"PluginInterface plugin = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, stepId);\nif (plugin == null) {\n  throw new KettleException(\"No plugin registered for id '\" + stepId + \"'\");\n}","typeGuard":"static PluginInterface requirePlugin(PluginRegistry reg, Class<? extends PluginTypeInterface> type, String id) {\n  PluginInterface p = reg.findPluginWithId(type, id);\n  if (p == null) throw new KettleException(\"Plugin not registered: \" + id);\n  return p;\n}","tryCatchPattern":"try {\n  Object o = PluginRegistry.getInstance().loadClass(plugin, StepMetaInterface.class);\n} catch (KettlePluginException e) {\n  if (plugin == null || e.getMessage().contains(\"Not a valid plugin\")) {\n    throw new KettleException(\"Plugin lookup failed before loadClass; id not registered\", e);\n  }\n}","preventionTips":["Never call loadClass without null-checking the plugin from findPluginWithId/findPluginByName.","Spell-check plugin ids; they are case-sensitive.","Check startup logs for registration failures that leave plugins unregistered.","Verify plugin folders are scanned (KETTLE_PLUGIN_FOLDERS) before lookups."],"tags":["kettle","plugins","registry","null"],"backgroundTag":"null-argument","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"}