pentaho/pentaho-kettle · error · KettleFileException
Unable to list jar files in plugin folder
Error message
Unable to list jar files in plugin folder '${folder}' What it means
PluginFolder.findJarFiles uses Apache VFS to list *.jar files in the configured plugin folder, wrapping failures in KettleFileException. This means the folder could not be read or iterated (does not exist, is not a directory, or I/O/permission failure), so no plugin jars could be discovered.
Solutions
- Verify the plugin folder path exists and is a directory: ls <folder> (or the configured KETTLE_PLUGIN_FOLDERS value).
- Fix the path/URI passed to PluginFolder (use an absolute path; check for typos and correct separators).
- Grant the process read+execute permission on the folder (chmod/chown).
- Check the nested cause exception in the KettleFileException for the underlying VFS/I/O reason.
Example fix
// before
PluginFolder folder = new PluginFolder("/opt/pentaho/plugns", false, true); // typo path
// after
PluginFolder folder = new PluginFolder("/opt/pentaho/plugins", false, true);
File dir = new File("/opt/pentaho/plugins");
if (!dir.isDirectory()) throw new IllegalStateException("Missing plugin folder: " + dir); Defensive patterns
Strategy: validation
Validate before calling
File dir = new File(folderPath);
if (!dir.isDirectory()) throw new IllegalStateException("Not a directory: " + folderPath);
if (!dir.canRead()) throw new IllegalStateException("Not readable: " + folderPath); Type guard
static boolean isReadableDirectory(java.io.File f) {
return f != null && f.isDirectory() && f.canRead();
} Try / catch
try {
jars = pluginFolder.findJarFiles(true);
} catch (KettleFileException e) {
log.error("Plugin folder unreadable: " + pluginFolder + " cause: " + e.getCause(), e);
} Prevention
- Validate plugin folder paths at startup before scanning.
- Use absolute paths and avoid manual URI string building.
- Ensure container/deployment scripts create plugin directories with correct permissions.
- Check the nested cause of KettleFileException to distinguish missing vs permission issues.
When it happens
Trigger: findJarFiles (called by libFiles/recursive scan) throws when VFS's FileObject.getChildren()/listFiles on the folder path raises any Exception — folder missing, path is a file, no read permission, or an invalid/unsupported VFS URI.
Common situations: KETTLE_PLUGIN_FOLDER or plugin folder configuration points to a directory that doesn't exist or was renamed; wrong path separator/URI scheme passed to PluginFolder; read permissions missing on the plugin directory (common in containerized installs); folder deleted after startup config was written.
Related errors
- Error opening new file
- ex.getMessage()
- GroupBy.Exception.UnableToCreateTemporaryFile
- Plugin's plugin.properties file could not be read.
- Cannot open control file
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/a72089b2fadabc3a.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/plugins/PluginFolder.java:136
FileObject folderObject = KettleVFS.getInstance( DefaultBowl.getInstance() ).getFileObject( this.getFolder() );
return folderObject.findFiles( new FileSelector() {
@Override
public boolean traverseDescendents( FileSelectInfo fileSelectInfo ) throws Exception {
FileObject fileObject = fileSelectInfo.getFile();
String folder = fileObject.getName().getBaseName();
FileObject kettleIgnore = fileObject.getChild( ".kettle-ignore" );
return includeLibJars || ( kettleIgnore == null && !"lib".equals( folder ) );
}
@Override
public boolean includeFile( FileSelectInfo fileSelectInfo ) throws Exception {
FileObject file = fileSelectInfo.getFile();
return file.isFile() && file.toString().endsWith( ".jar" );
}
} );
} catch ( Exception e ) {
throw new KettleFileException( "Unable to list jar files in plugin folder '" + toString() + "'", e );
}
}
/**
* @return the folder
*/
@Override
public String getFolder() {
return folder;
}
/**
* @param folder
* the folder to set
*/
public void setFolder( String folder ) {
this.folder = folder;
}View on GitHub (pinned to f3058517a1)