pentaho/pentaho-kettle · error · KettleException

KettleDatabaseRepositorySecurityProvider.ERROR_0001_USER_NAME_ALREADY_EXISTS

KettleDatabaseRepositorySecurityProvider.ERROR_0001_USER_NAME_ALREADY_EXISTS

Error message

KettleDatabaseRepositorySecurityProvider.ERROR_0001_USER_NAME_ALREADY_EXISTS

What it means

Thrown by KettleDatabaseRepositorySecurityProvider.saveUserInfo when a user with the given login name already exists in the database repository. The delegate looks up an existing ObjectId for the user's login before inserting; if found, creation of a duplicate user is prohibited. This prevents duplicate user accounts with identical login names in the repository.

Solutions

  1. Check existence first with securityProvider.getUserID(login) / getUser(login) and update the existing user instead of saving a new one
  2. Use an update path (rename the existing user or modify it) rather than creating a new record
  3. Catch KettleException and surface a 'user already exists' message to the user, prompting for a different login
  4. Wrap creation in a synchronized/transactional section if concurrent provisioning is possible

Example fix

// before
userInfo.setLogin("admin");
repo.getUserID("admin"); // may already exist
repo.securityProvider.saveUserInfo(userInfo); // throws

// after
if (repo.getUserID("admin") == null) {
  repo.securityProvider.saveUserInfo(userInfo);
} else {
  userInfo.setLogin("admin2");
  repo.securityProvider.saveUserInfo(userInfo);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (repository.getSecurityProvider().getUserID(userInfo.getLogin()) != null) { throw new IllegalArgumentException("User login already exists: " + userInfo.getLogin()); }

Type guard

boolean userExists = (login != null && repository.getUserID(login) != null);

Try / catch

try { securityProvider.saveUserInfo(userInfo); } catch (KettleException e) { if (e.getMessage().contains("already exists")) { /* prompt rename */ } else { throw e; } }

Prevention

When it happens

Trigger: Calling repository.securityProvider.saveUserInfo(userInfo) (or addUser) with a userInfo whose getLogin() already matches an existing row in the repository user table; exactMatch != null from userDelegate.getUserID(userLogin).

Common situations: Administrators re-running a user-provisioning script, importing users that already exist, or a UI race where two sessions create the same login simultaneously.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/repository/kdr/KettleDatabaseRepositorySecurityProvider.java:111

   * @throws IllegalArgumentException if {@code userInfo.getObjectId() != null}
   */
  public void saveUserInfo( IUser userInfo ) throws KettleException {
    normalizeUserInfo( userInfo );
    if ( !validateUserInfo( userInfo ) ) {
      throw new KettleException( BaseMessages.getString( KettleDatabaseRepositorySecurityProvider.class,
        "KettleDatabaseRepositorySecurityProvider.ERROR_0001_UNABLE_TO_CREATE_USER" ) );
    }

    if ( userInfo.getObjectId() != null ) {
      // not a message for UI
      throw new IllegalArgumentException( "Use updateUser() for updating" );
    }

    String userLogin = userInfo.getLogin();
    ObjectId exactMatch = userDelegate.getUserID( userLogin );
    if ( exactMatch != null ) {
      // found the corresponding record in db, prohibit creation!
      throw new KettleException( BaseMessages.getString( KettleDatabaseRepositorySecurityProvider.class,
        "KettleDatabaseRepositorySecurityProvider.ERROR_0001_USER_NAME_ALREADY_EXISTS" ) );
    }

    userDelegate.saveUserInfo( userInfo );
  }

  public void validateAction( RepositoryOperation... operations ) throws KettleException, KettleSecurityException {

  }

  public synchronized void delUser( ObjectId id_user ) throws KettleException {
    repository.connectionDelegate.performDelete( "DELETE FROM "
      + repository.quoteTable( KettleDatabaseRepository.TABLE_R_USER ) + " WHERE "
      + repository.quote( KettleDatabaseRepository.FIELD_USER_ID_USER ) + " = ? ", id_user );
  }

  public synchronized ObjectId getUserID( String login ) throws KettleException {
    return userDelegate.getUserID( login );

View on GitHub (pinned to f3058517a1)