pentaho/pentaho-kettle · error · KettlePluginException

PLUGINREGISTRY001

PLUGINREGISTRY001

Error message

Not a valid plugin

What it means

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.

Solutions

  1. Check the return of registry.findPluginWithId/findPluginByName for null before calling loadClass.
  2. Verify the plugin id used in the lookup matches the registered id exactly (case-sensitive).
  3. Confirm the plugin actually registered: check startup logs for plugin registration errors (e.g. error 300/303) that left it unregistered.
  4. Ensure the plugin folder containing the jar is in the scanned plugin folders list.

Example fix

// before
PluginInterface plugin = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, stepId);
Object obj = PluginRegistry.getInstance().loadClass(plugin, StepMetaInterface.class); // NPE risk

// after
PluginInterface plugin = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, stepId);
if (plugin == null) {
  throw new KettleException("Step plugin not registered for id: " + stepId);
}
Object obj = PluginRegistry.getInstance().loadClass(plugin, StepMetaInterface.class);
Defensive patterns

Strategy: type-guard

Validate before calling

PluginInterface plugin = PluginRegistry.getInstance().findPluginWithId(StepPluginType.class, stepId);
if (plugin == null) {
  throw new KettleException("No plugin registered for id '" + stepId + "'");
}

Type guard

static PluginInterface requirePlugin(PluginRegistry reg, Class<? extends PluginTypeInterface> type, String id) {
  PluginInterface p = reg.findPluginWithId(type, id);
  if (p == null) throw new KettleException("Plugin not registered: " + id);
  return p;
}

Try / catch

try {
  Object o = PluginRegistry.getInstance().loadClass(plugin, StepMetaInterface.class);
} catch (KettlePluginException e) {
  if (plugin == null || e.getMessage().contains("Not a valid plugin")) {
    throw new KettleException("Plugin lookup failed before loadClass; id not registered", e);
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/83b3aec56a9d8589. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java:478

    supplementalPlugin.addFactory( tClass, callable );
  }

  private String createSupplemantalKey( String pluginName, String id ) {
    return pluginName + "-" + id + SUPPLEMENTALS_SUFFIX;
  }

  /**
   * Load and instantiate the plugin class specified
   *
   * @param plugin      the plugin to load
   * @param pluginClass the class to be loaded
   * @return The instantiated class
   * @throws KettlePluginException In case there was a class loading problem somehow
   */
  @SuppressWarnings( "unchecked" )
  public <T> T loadClass( PluginInterface plugin, Class<T> pluginClass ) throws KettlePluginException {
    if ( plugin == null ) {
      throw new KettlePluginException( BaseMessages.getString(
          PKG, "PluginRegistry.RuntimeError.NoValidStepOrPlugin.PLUGINREGISTRY001" ) );
    }

    if ( plugin instanceof ClassLoadingPluginInterface ) {
      T aClass = ( (ClassLoadingPluginInterface) plugin ).loadClass( pluginClass );
      if ( aClass == null ) {
        throw new KettlePluginClassMapException( BaseMessages
            .getString( PKG, "PluginRegistry.RuntimeError.NoValidClassRequested.PLUGINREGISTRY002", plugin.getName(),
                pluginClass.getName() ) );
      } else {
        return aClass;
      }
    } else {
      String className = plugin.getClassMap().get( pluginClass );
      if ( className == null ) {
        // Look for supplemental plugin supplying extra classes
        for ( String id : plugin.getIds() ) {
          try {

View on GitHub (pinned to f3058517a1)