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

  1. Inspect e.getCause() (KettleDatabaseException/SQLException) and fix the underlying DB issue
  2. Verify the repository connection is alive and writable; reconnect and retry
  3. Confirm the parent directory still exists before saving a new child
  4. 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

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


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)