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
- Fix or remove the alternative plugin file configuration so it points at an existing, readable file.
- Verify the kettle-core jar (or plugin type jar) containing the native XML is on the classpath and not corrupted.
- Check the wrapped cause (getCause()) for the exact IO error (file not found vs permission).
- 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
- Point any alternative plugin file setting at an existing, readable file or unset it.
- Keep the kettle-core jar (with native plugin XMLs) intact on the classpath.
- Don't strip XML resources in shaded/assembly packaging.
- Check getCause() first — it names the real IO problem.
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
- No ID specified for plugin with class
- Unable to find native plugins definition file
- Unable to load class
- AccessInput.Exception.CouldnotFindField
- AccessInput.Log.NoField
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)