pentaho/pentaho-kettle · error · KettleException
This directory is not empty!
Error message
This directory is not empty!
What it means
Thrown by delRepositoryDirectory when deleteNonEmptyFolder is false but the directory still contains transformations, jobs, or subdirectories. The guard checks trans.length==0 && jobs.length==0 && subDirectories.length==0 and refuses to delete non-empty folders to prevent silent data loss. It is a deliberate precondition failure, not a database error.
Solutions
- Pass deleteNonEmptyFolder=true only if recursive deletion is intended (destructive)
- First delete or move all transformations, jobs, and subdirectories inside it, then retry with false
- Check contents beforehand via repository.getJobNames/getTransformationNames(dir) and getSubDirectoryIDs
- Ask the user to confirm before enabling recursive delete
Example fix
// before
repository.delRepositoryDirectory( dir, false ); // throws if not empty
// after
if ( repository.getJobNames( dir, false ).length == 0
&& repository.getTransformationNames( dir, false ).length == 0
&& repository.getDirectoryIDs( dir.getObjectId() ).length == 0 ) {
repository.delRepositoryDirectory( dir, false );
} Defensive patterns
Strategy: validation
Validate before calling
boolean isEmptyDir = repository.getJobNames( dir, false ).length == 0
&& repository.getTransformationNames( dir, false ).length == 0
&& repository.getSubDirectoryIDs( dir.getObjectId() ).length == 0;
if ( !isEmptyDir && !forceRecursiveDelete ) {
// abort: refuse to delete a non-empty folder
} Try / catch
try {
repository.delRepositoryDirectory( dir, false );
} catch ( KettleException e ) {
if ( "This directory is not empty!".equals( e.getMessage() ) ) {
// enumerate and delete children first, or require explicit confirmation
}
} Prevention
- Enumerate jobs/transformations/subdirectories before deleting
- Only pass deleteNonEmptyFolder=true with explicit user confirmation
- Clean up folder leaves before pruning parent folders in scripts
When it happens
Trigger: repository.delRepositoryDirectory(dir, false) invoked on a folder that still holds any transformations, jobs, or child directories.
Common situations: Users trying to prune a folder tree whose leaves were not cleaned first; automated cleanup scripts that assumed the folder was empty; UI operations where the folder still contains hidden or recently added items.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- A connection of type PALO is expected
- A connection of type PALO is expected
- A server socket allocation always has to accompanied by a…
- A server socket allocation always has to accompanied by…
- Argument is required.
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/b26df2a03a0a4d33.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/repository/kdr/delegates/KettleDatabaseRepositoryDirectoryDelegate.java:318
repository.commit();
} catch ( Exception e ) {
throw new KettleException( "Unable to save directory [" + dir + "] in the repository", e );
}
}
public void delRepositoryDirectory( RepositoryDirectoryInterface dir, boolean deleteNonEmptyFolder ) throws KettleException {
try {
if ( !deleteNonEmptyFolder ) {
String[] trans = repository.getTransformationNames( dir.getObjectId(), false ); // TODO : include or exclude
// deleted objects?
String[] jobs = repository.getJobNames( dir.getObjectId(), false ); // TODO : include or exclude deleted
// objects?
ObjectId[] subDirectories = repository.getSubDirectoryIDs( dir.getObjectId() );
if ( trans.length == 0 && jobs.length == 0 && subDirectories.length == 0 ) {
repository.directoryDelegate.deleteDirectory( dir.getObjectId() );
repository.commit();
} else {
throw new KettleException( "This directory is not empty!" );
}
} else {
repository.directoryDelegate.deleteDirectory( dir );
repository.commit();
}
} catch ( Exception e ) {
throw new KettleException( "Unexpected error deleting repository directory:", e );
}
}
/**
* @deprecated use {@link #renameRepositoryDirectory(ObjectId, RepositoryDirectoryInterface, String)}
*
* @param dir
* @return
* @throws KettleException
*/
@DeprecatedView on GitHub (pinned to f3058517a1)