{"record":{"id":"790e87857ffeca8f","repo":"pentaho/pentaho-kettle","slug":"kettledatabaserepositorysecurityprovider-error-0001-user","errorCode":"KettleDatabaseRepositorySecurityProvider.ERROR_0001_USER_NAME_ALREADY_EXISTS","errorMessage":"KettleDatabaseRepositorySecurityProvider.ERROR_0001_USER_NAME_ALREADY_EXISTS","messagePattern":"KettleDatabaseRepositorySecurityProvider\\.ERROR_0001_USER_NAME_ALREADY_EXISTS","errorType":"error_code","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/repository/kdr/KettleDatabaseRepositorySecurityProvider.java","lineNumber":111,"sourceCode":"   * @throws IllegalArgumentException if {@code userInfo.getObjectId() != null}\n   */\n  public void saveUserInfo( IUser userInfo ) throws KettleException {\n    normalizeUserInfo( userInfo );\n    if ( !validateUserInfo( userInfo ) ) {\n      throw new KettleException( BaseMessages.getString( KettleDatabaseRepositorySecurityProvider.class,\n        \"KettleDatabaseRepositorySecurityProvider.ERROR_0001_UNABLE_TO_CREATE_USER\" ) );\n    }\n\n    if ( userInfo.getObjectId() != null ) {\n      // not a message for UI\n      throw new IllegalArgumentException( \"Use updateUser() for updating\" );\n    }\n\n    String userLogin = userInfo.getLogin();\n    ObjectId exactMatch = userDelegate.getUserID( userLogin );\n    if ( exactMatch != null ) {\n      // found the corresponding record in db, prohibit creation!\n      throw new KettleException( BaseMessages.getString( KettleDatabaseRepositorySecurityProvider.class,\n        \"KettleDatabaseRepositorySecurityProvider.ERROR_0001_USER_NAME_ALREADY_EXISTS\" ) );\n    }\n\n    userDelegate.saveUserInfo( userInfo );\n  }\n\n  public void validateAction( RepositoryOperation... operations ) throws KettleException, KettleSecurityException {\n\n  }\n\n  public synchronized void delUser( ObjectId id_user ) throws KettleException {\n    repository.connectionDelegate.performDelete( \"DELETE FROM \"\n      + repository.quoteTable( KettleDatabaseRepository.TABLE_R_USER ) + \" WHERE \"\n      + repository.quote( KettleDatabaseRepository.FIELD_USER_ID_USER ) + \" = ? \", id_user );\n  }\n\n  public synchronized ObjectId getUserID( String login ) throws KettleException {\n    return userDelegate.getUserID( login );","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/repository/kdr/KettleDatabaseRepositorySecurityProvider.java#L93-L129","documentation":"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.","triggerScenarios":"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).","commonSituations":"Administrators re-running a user-provisioning script, importing users that already exist, or a UI race where two sessions create the same login simultaneously.","solutions":["Check existence first with securityProvider.getUserID(login) / getUser(login) and update the existing user instead of saving a new one","Use an update path (rename the existing user or modify it) rather than creating a new record","Catch KettleException and surface a 'user already exists' message to the user, prompting for a different login","Wrap creation in a synchronized/transactional section if concurrent provisioning is possible"],"exampleFix":"// before\nuserInfo.setLogin(\"admin\");\nrepo.getUserID(\"admin\"); // may already exist\nrepo.securityProvider.saveUserInfo(userInfo); // throws\n\n// after\nif (repo.getUserID(\"admin\") == null) {\n  repo.securityProvider.saveUserInfo(userInfo);\n} else {\n  userInfo.setLogin(\"admin2\");\n  repo.securityProvider.saveUserInfo(userInfo);\n}","handlingStrategy":"try-catch","validationCode":"if (repository.getSecurityProvider().getUserID(userInfo.getLogin()) != null) { throw new IllegalArgumentException(\"User login already exists: \" + userInfo.getLogin()); }","typeGuard":"boolean userExists = (login != null && repository.getUserID(login) != null);","tryCatchPattern":"try { securityProvider.saveUserInfo(userInfo); } catch (KettleException e) { if (e.getMessage().contains(\"already exists\")) { /* prompt rename */ } else { throw e; } }","preventionTips":["Always look up the login before creating a new user","Use unique login conventions (e.g., domain prefix) to avoid collisions","Serialize user provisioning scripts","Catch and surface the error in UI instead of failing silently"],"tags":["repository","duplicate-user","pdi"],"backgroundTag":"file-already-exists","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}