pentaho/pentaho-kettle · error · KettleException

ERROR_0009_UNABLE_TO_DELETE_ROLES

ERROR_0009_UNABLE_TO_DELETE_ROLES

Error message

UserRoleDelegate.ERROR_0009_UNABLE_TO_DELETE_ROLES

What it means

Thrown by UserRoleDelegate.deleteRoles(List<IRole>) when the role deletion fails through userRoleWebService.deleteRoles. The exception is wrapped in a KettleException with ERROR_0009_UNABLE_TO_DELETE_ROLES (no parameter). After a successful remote delete the local lookup cache is updated and the role list change event is fired — those never run on failure.

Solutions

  1. Inspect the wrapped cause for the server rejection reason.
  2. Remove all user assignments from the roles before deleting.
  3. Do not attempt to delete protected/system or LDAP-provided roles.
  4. Ensure the client user has Administrator security permissions.

Example fix

// before
userRoleDelegate.deleteRoles(roles); // fails if roles still assigned
// after
for (IRole role : roles) {
  ((IEERole) role).setUsers(new ArrayList<IUser>());
  userRoleDelegate.updateRole(role); // unbind users first
}
userRoleDelegate.deleteRoles(roles);
Defensive patterns

Strategy: try-catch

Validate before calling

List<String> protectedRoles = Arrays.asList("Admin", "Authenticated");
boolean safe = roles.stream().noneMatch(r -> protectedRoles.contains(r.getName()));
if (!safe) throw new IllegalArgumentException("Refusing to delete protected/system roles");

Try / catch

try {
  userRoleDelegate.deleteRoles(roles);
} catch (KettleException e) {
  log.error("Role delete failed: " + e.getCause(), e);
  // retry per-role to isolate failures
  for (IRole r : roles) { try { userRoleDelegate.deleteRole(r.getName()); } catch (KettleException ignored) {} }
}

Prevention

When it happens

Trigger: Calling deleteRoles(roles) when the web service throws: server refuses deletion (role still bound to users/permissions, system role), insufficient admin permissions, transport failure, or expired session.

Common situations: Deleting default/system Pentaho roles (Admin, Authenticated) that the server protects; cleanup scripts hitting roles still assigned to users; security provider (LDAP) roles that are not server-manageable.

Related errors


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

Appendix: source

Thrown at plugins/pur/core/src/main/java/org/pentaho/di/repository/pur/UserRoleDelegate.java:378

  private KettleException roleExistsException() {
    return new KettleException( BaseMessages.getString( UserRoleDelegate.class,
        "UserRoleDelegate.ERROR_0016_ROLE_NAME_ALREADY_EXISTS" ) );
  }

  private KettleException cannotCreateRoleException( IRole role, Exception e ) {
    return new KettleException( BaseMessages.getString( UserRoleDelegate.class,
        "UserRoleDelegate.ERROR_0008_UNABLE_TO_CREATE_ROLE", role.getName() ), e );
  }

  public void deleteRoles( List<IRole> roles ) throws KettleException {
    ensureHasPermissions();

    try {
      userRoleWebService.deleteRoles( UserRoleHelper.convertToPentahoProxyRoles( roles ) );
      lookupCache.removeRolesFromLookupSet( roles );
      fireUserRoleListChange();
    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString( UserRoleDelegate.class,
          "UserRoleDelegate.ERROR_0009_UNABLE_TO_DELETE_ROLES" ), e ); //$NON-NLS-1$
    }
  }

  public IRole getRole( String name ) throws KettleException {
    ensureHasPermissions();

    try {
      return UserRoleHelper.convertFromProxyPentahoRole( userRoleWebService, UserRoleHelper.getProxyPentahoRole(
          userRoleWebService, name ), lookupCache, rsm );
    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString( UserRoleDelegate.class,
          "UserRoleDelegate.ERROR_0010_UNABLE_TO_GET_ROLE", name ), e ); //$NON-NLS-1$
    }
  }

  public List<IRole> getRoles() throws KettleException {
    try {

View on GitHub (pinned to f3058517a1)