pentaho/pentaho-kettle · error · KettlePluginException

Unable to load native plugins

Error message

Unable to load native plugins '${xmlFile}'

What it means

BasePluginType.registerNatives loads the plugin type's native plugin XML definition (e.g. steps/type-list.xml). If the primary classpath resource can't be read and an alternative plugin file is configured, it retries via getFileInputStreamExternal(xmlFile); if that retry also fails, KettlePluginException is thrown wrapping the underlying IO problem. This means the plugin system cannot read its built-in plugin catalog.

Solutions

  1. Fix or remove the alternative plugin file configuration so it points at an existing, readable file.
  2. Verify the kettle-core jar (or plugin type jar) containing the native XML is on the classpath and not corrupted.
  3. Check the wrapped cause (getCause()) for the exact IO error (file not found vs permission).
  4. Reinstall/restore the Pentaho installation directory if built-in resources are missing.

Example fix

// before
System.setProperty("KETTLE_PLUGIN_FILE", "/opt/wrong/plugins.xml");
// after
System.setProperty("KETTLE_PLUGIN_FILE", "/opt/pentaho/plugins/plugins.xml"); // existing file
Defensive patterns

Strategy: try-catch

Validate before calling

String alt = System.getenv().getOrDefault("KETTLE_PLUGIN_FILE", "");
if (!alt.isEmpty() && !new File(alt).canRead()) {
  throw new IllegalStateException("Alternative plugin file unreadable: " + alt);
}

Type guard

static boolean canReadResource(ClassLoader cl, String path) {
  try (InputStream in = cl.getResourceAsStream(path)) { return in != null; }
  catch (Exception e) { return false; }
}

Try / catch

try {
  pluginType.searchPlugins();
} catch (KettlePluginException e) {
  log.logError("Failed to load native plugins: " + e.getCause(), e);
}

Prevention

When it happens

Trigger: registerNatives (invoked by searchPlugins()) where an alternative plugin file is set, the classpath resource stream is null, and getFileInputStreamExternal throws — e.g. the alternative path doesn't exist or is unreadable.

Common situations: KETTLE_*/alternative plugin config pointing at a missing or mis-spelled file; corrupted installation where the jar containing the native plugin XML is absent from the classpath; packaging a shaded jar that dropped plugin XML resources.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/plugins/BasePluginType.java:215

        xmlFile = alternative;
      }
    }

    // Load the plugins for this file...
    //
    InputStream inputStream = null;
    try {
      inputStream = getResAsStreamExternal( xmlFile );
      if ( inputStream == null ) {
        inputStream = getResAsStreamExternal( "/" + xmlFile );
      }

      if ( !Utils.isEmpty( getAlternativePluginFile() ) && inputStream == null && !Utils.isEmpty( alternative ) ) {
        // Retry to load a regular file...
        try {
          inputStream = getFileInputStreamExternal( xmlFile );
        } catch ( Exception e ) {
          throw new KettlePluginException( "Unable to load native plugins '" + xmlFile + "'", e );
        }
      }

      if ( inputStream == null ) {
        if ( isReturn() ) {
          return;
        } else {
          throw new KettlePluginException( "Unable to find native plugins definition file: " + xmlFile );
        }
      }

      registerPlugins( inputStream );

    } catch ( KettleXMLException e ) {
      throw new KettlePluginException( "Unable to read the kettle XML config file: " + xmlFile, e );
    } finally {
      IOUtils.closeQuietly( inputStream );
    }

View on GitHub (pinned to f3058517a1)