pentaho/pentaho-kettle · error · KettleException
Unable to save directory [dir] in the repository
Error message
Unable to save directory [dir] in the repository
What it means
Wrapper KettleException thrown by saveRepositoryDirectory when any exception occurs while persisting a directory to the database (insert or update of the r_directory row, or the commit). The original exception is the cause; the message includes the directory's toString. This means the directory metadata was not saved and the transaction was not committed.
Solutions
- Inspect e.getCause() (KettleDatabaseException/SQLException) and fix the underlying DB issue
- Verify the repository connection is alive and writable; reconnect and retry
- Confirm the parent directory still exists before saving a new child
- Check for name conflicts and DB constraint violations on r_directory
Example fix
// before
repository.saveRepositoryDirectory( dir, "/new/path", false );
// after
try {
repository.saveRepositoryDirectory( dir, "/new/path", false );
} catch ( KettleException e ) {
Throwable cause = e.getCause();
log.error( "Directory save failed: " + ( cause != null ? cause.getMessage() : e.getMessage() ) );
} Defensive patterns
Strategy: try-catch
Validate before calling
// verify parent exists and connection is alive before saving
RepositoryDirectoryInterface parent = repo.findDirectory( parentPath );
if ( parent == null || parent.getObjectId() == null ) {
throw new IllegalStateException( "Parent directory missing" );
} Try / catch
try {
repository.saveRepositoryDirectory( dir, path, hideInTree );
} catch ( KettleException e ) {
Throwable cause = e.getCause();
if ( cause instanceof KettleDatabaseException ) { /* reconnect and retry */ }
} Prevention
- Confirm the repository connection is writable before bulk directory creation
- Refresh ObjectIds before save; another client may have deleted the parent
- Check DB constraints and column lengths for directory names
- Commit intentionally; avoid leaving transactions open around the save
When it happens
Trigger: Calling repository.saveRepositoryDirectory(dir, path, hide) / createRepositoryDirectory when insertDirectory/updateDirectory fails: DB connection error, constraint violation, oversized name, or the parent ObjectId no longer exists.
Common situations: Repository database read-only or out of space; parent directory deleted by another client between load and save; network interruption to the repository RDBMS; duplicate directory name at insert time.
Related errors
- Database.Exception.UnableToDisableAutoCommit
- Database.Exception.UnableToEnableAutoCommit
- Database.Exception.UnableToReleaseSavepoint
- Database.Exception.UnableToRollbackToSavepoint
- Database.Exception.UnableToSetSavepoint
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/528476a1b59a0388.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/repository/kdr/delegates/KettleDatabaseRepositoryDirectoryDelegate.java:302
+ quoteTable( KettleDatabaseRepository.TABLE_R_DIRECTORY ) + " WHERE "
+ quote( KettleDatabaseRepository.FIELD_DIRECTORY_ID_DIRECTORY_PARENT ) + " = ? ORDER BY "
+ quote( KettleDatabaseRepository.FIELD_DIRECTORY_DIRECTORY_NAME ), id_directory );
}
public void saveRepositoryDirectory( RepositoryDirectoryInterface dir ) throws KettleException {
try {
ObjectId id_directory_parent = null;
if ( dir.getParent() != null ) {
id_directory_parent = dir.getParent().getObjectId();
}
dir.setObjectId( insertDirectory( id_directory_parent, dir ) );
log.logDetailed( "New id of directory = " + dir.getObjectId() );
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 {View on GitHub (pinned to f3058517a1)