pentaho/pentaho-kettle · error · KettlePluginException

PLUGINREGISTRY004

PLUGINREGISTRY004

Error message

Unable to instantiate class

What it means

In loadClass, after the class is loaded, cl.newInstance() instantiates it. An InstantiationException is rethrown as KettlePluginException 'Unable to instantiate class' (PLUGINREGISTRY004). Java throws InstantiationException when the class is abstract, an interface, or has no accessible no-arg constructor.

Solutions

  1. Point the plugin metadata (annotation/plugin.xml) at the concrete class, not an interface or abstract class.
  2. Add a public no-argument constructor to the plugin class.
  3. Make the class public and non-abstract.
  4. If the class needs parameters, implement the expected plugin pattern (Kettle instantiates via no-arg constructor then calls init/setDefaults).

Example fix

// before
public class MyStepMeta extends BaseStepMeta {
  public MyStepMeta(String config) { ... } // no no-arg ctor
}

// after
public class MyStepMeta extends BaseStepMeta {
  public MyStepMeta() { }
  public MyStepMeta(String config) { this(); ... }
}
Defensive patterns

Strategy: validation

Validate before calling

Class<?> cl = pluginClassLoader.loadClass(fqn);
int mods = cl.getModifiers();
if (Modifier.isAbstract(mods) || Modifier.isInterface(mods) || !Modifier.isPublic(mods)) {
  throw new IllegalStateException("Cannot instantiate: " + fqn);
}
cl.getDeclaredConstructor(); // throws if no no-arg ctor

Type guard

static boolean isInstantiable(Class<?> c) {
  int m = c.getModifiers();
  try {
    c.getDeclaredConstructor();
  } catch (NoSuchMethodException e) { return false; }
  return Modifier.isPublic(m) && !Modifier.isAbstract(m) && !c.isInterface();
}

Try / catch

try {
  return PluginRegistry.getInstance().loadClass(plugin, pluginClass);
} catch (KettlePluginException e) {
  if (e.getMessage().contains("Unable to instantiate")) {
    log.error("Check that " + plugin + " maps a concrete public class with a no-arg constructor", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: cl.newInstance() on the resolved plugin class throws InstantiationException — the mapped class is abstract or an interface, or lacks a public no-argument constructor, so the registry cannot create an instance.

Common situations: A plugin metadata entry points at the interface or abstract base class instead of the concrete implementation; the plugin class defines only parameterized constructors; Kotlin/other-language class compiled without a no-arg constructor; class is not public.

Related errors


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

Appendix: source

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

      }

      try {
        Class<? extends T> cl;
        if ( plugin.isNativePlugin() ) {
          cl = (Class<? extends T>) Class.forName( className );
        } else {
          ClassLoader ucl = getClassLoader( plugin );

          // Load the class.
          cl = (Class<? extends T>) ucl.loadClass( className );
        }

        return cl.newInstance();
      } catch ( ClassNotFoundException e ) {
        throw new KettlePluginException( BaseMessages.getString(
            PKG, "PluginRegistry.RuntimeError.ClassNotFound.PLUGINREGISTRY003" ), e );
      } catch ( InstantiationException e ) {
        throw new KettlePluginException( BaseMessages.getString(
            PKG, "PluginRegistry.RuntimeError.UnableToInstantiateClass.PLUGINREGISTRY004" ), e );
      } catch ( IllegalAccessException e ) {
        throw new KettlePluginException( BaseMessages.getString(
            PKG, "PluginRegistry.RuntimeError.IllegalAccessToClass.PLUGINREGISTRY005" ), e );
      } catch ( Throwable e ) {
        e.printStackTrace();
        throw new KettlePluginException( BaseMessages.getString(
            PKG, "PluginRegistry.RuntimeError.UnExpectedErrorLoadingClass.PLUGINREGISTRY007" ), e );
      }
    }
  }

  /**
   * Add a PluginType to be managed by the registry
   *
   * @param type
   */
  public static void addPluginType( PluginTypeInterface type ) {

View on GitHub (pinned to f3058517a1)