pentaho/pentaho-kettle · error · KettlePluginException

PLUGINREGISTRY007

PLUGINREGISTRY007

Error message

Unexpected error loading class:

What it means

PLUGINREGISTRY007 is thrown by PluginRegistry.loadClass when any unexpected Throwable (not ClassNotFoundException, InstantiationException, or IllegalAccessException) escapes while instantiating a plugin class via Class.forName().newInstance(). It is a catch-all in Kettle's plugin registry: the plugin id resolved to a class, but constructing it blew up in an unforeseen way. The original Throwable is chained as the cause and printed to stderr before the KettlePluginException is thrown.

Solutions

  1. Inspect the chained 'cause' (the stack trace printed to stderr) to identify the real Throwable and fix the underlying class-loading or initialization problem.
  2. Verify the plugin jar version matches the Kettle/PDI runtime version; redeploy a clean copy of the plugin directory.
  3. Check for duplicate/conflicting copies of the plugin class on the classpath and remove stale jars from lib/ or the plugin folder.
  4. If you own the plugin class, move risky work out of the static initializer and constructor so instantiation cannot throw.
  5. If you are a caller, catch KettlePluginException and fall back to a default implementation or fail fast with a clear message.

Example fix

// before: deployment mixes jar versions
plugins/myplugin/myplugin-8.0.jar  vs. runtime PDI 9.x
// after
plugins/myplugin/myplugin-9.2.jar  (matching runtime version); inspect printStackTrace() output for the chained cause
Defensive patterns

Strategy: try-catch

Validate before calling

String cls = plugin.getMainClass() != null ? plugin.getMainClass() : className;
if (cls == null || cls.isEmpty()) throw new IllegalStateException("Plugin " + plugin + " has no class to load");
try { Class.forName(cls, false, getClass().getClassLoader()); } catch (Throwable t) { /* resolve before loadClass */ }

Type guard

boolean isLoadable(String className) {
  try { Class.forName(className, false, getClass().getClassLoader()); return true; }
  catch (Throwable t) { return false; }
}

Try / catch

try {
  T instance = PluginRegistry.getInstance().loadClass(plugin, className, MyInterface.class);
} catch (KettlePluginException e) {
  LOG.error("Plugin class instantiation failed (PLUGINREGISTRY007)", e); // inspect e.getCause()
  throw new DeploymentException("Bad plugin jar/version: " + plugin, e);
}

Prevention

When it happens

Trigger: Calling PluginRegistry.loadClass(PluginInterface, Class<T>) or loadClass(pluginId, className, Class<T>) where the target class's static initializer, no-arg constructor, or newInstance() path throws a RuntimeException/Error (e.g. ExceptionInInitializerError, NoSuchMethodError from mismatched jars, ClassFormatError from a corrupted jar), and the plugin's declared class instantiation path is exercised.

Common situations: A plugin jar is compiled against a different Kettle/metadata version than the runtime (NoSuchMethodError/NoClassDefFoundError surfacing as Throwable); a plugin class throws in a static initializer; a corrupted or partially deployed plugin jar; classpath conflicts where two plugin versions shadow each other.

Related errors


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

Appendix: source

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

          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 ) {
    pluginTypes.add( type );
  }

  /**
   * Added so we can tell when types have been added (but not necessarily registered)
   *
   * @return the list of added plugin types

View on GitHub (pinned to f3058517a1)