pentaho/pentaho-kettle · error · KettleException

Unable to delete directory with path [

Error message

Unable to delete directory with path [

What it means

Catch-all wrapper in deleteRepositoryDirectory: any exception from the guards above or from pur.deleteFile is wrapped as "Unable to delete directory with path [...]" with the root cause chained; the write lock is released in finally.

Solutions

  1. Inspect e.getCause() — if it is RepositoryObjectAccessException USER_HOME_DIR, honor it and skip the folder.
  2. Verify the user has delete permission on the folder (PUC security settings).
  3. Re-fetch the directory to refresh its ObjectId before retrying the delete.
  4. Delete children individually if a server-side constraint blocks the recursive delete.

Example fix

// before
repo.deleteRepositoryDirectory(dir, true);
// after
try { repo.deleteRepositoryDirectory(repo.findDirectory(dir.getPath()), true); } catch (KettleException e) { logger.warn("delete {} failed: {}", dir.getPath(), e.getCause()); }
Defensive patterns

Strategy: try-catch

Validate before calling

if (repo.findDirectory(dir.getPath()) == null) return; // already gone

Try / catch

try { repo.deleteRepositoryDirectory(dir, true); } catch (KettleException e) { Throwable c = e.getCause(); if (c instanceof RepositoryObjectAccessException) handleAccess((RepositoryObjectAccessException) c); else retryWithFreshObjectId(dir); }

Prevention

When it happens

Trigger: pur.deleteFile fails — the caller lacks delete permission, the folder contains undeletable content, the ObjectId is stale after concurrent modification, or a JCR/server error occurs; also wraps RepositoryObjectAccessException from the home-folder guards into a KettleException.

Common situations: Deleting folders under /public without delete ACLs; another client moved/deleted the folder first; recursive deletions partially failing mid-tree.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/8d599966ab165f66. Report an issue: GitHub.

Appendix: source

Thrown at plugins/pur/core/src/main/java/org/pentaho/di/repository/pur/PurRepository.java:583

      folder = pur.getFileById( dir.getObjectId().getId() );
      // Fetch the user's home directory
      homeFolder = pur.getFile( ClientRepositoryPaths.getUserHomeFolderPath( user.getLogin() ) );

      // Make sure the user is not trying to delete their own home directory
      if ( isSameOrAncestorFolder( folder, homeFolder ) ) {
        // Then throw an exception that the user cannot delete their own home directory
        throw new KettleException( "You are not allowed to delete your home folder." );
      }

      if ( !deleteHomeDirectories && isUserHomeDirectory( folder ) ) {
        throw new RepositoryObjectAccessException( "Cannot delete another users home directory",
          RepositoryObjectAccessException.AccessExceptionType.USER_HOME_DIR );
      }

      pur.deleteFile( dir.getObjectId().getId(), null );
      rootRef.clearRef();
    } catch ( Exception e ) {
      throw new KettleException( "Unable to delete directory with path [" + getPath( null, dir, null ) + "]", e );
    } finally {
      readWriteLock.writeLock().unlock();
    }
  }

  @Override
  public ObjectId renameRepositoryDirectory( final ObjectId dirId, final RepositoryDirectoryInterface newParent,
                                             final String newName ) throws KettleException {
    return renameRepositoryDirectory( dirId, newParent, newName, false );
  }

  @Override
  public ObjectId renameRepositoryDirectory( final ObjectId dirId, final RepositoryDirectoryInterface newParent,
                                             final String newName, final boolean renameHomeDirectories )
    throws KettleException {
    // dir ID is used to find orig obj; new parent is used as new parent (might be null meaning no change in parent);
    // new name is used as new file name (might be null meaning no change in name)
    String finalName = null;

View on GitHub (pinned to f3058517a1)