{"record":{"id":"65f2423d30612b4e","repo":"SonarSource/sonarqube","slug":"old-password-incorrect","errorCode":"old_password_incorrect","errorMessage":"Incorrect password","messagePattern":"Incorrect password","errorType":"validation","errorClass":"PasswordException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java","lineNumber":193,"sourceCode":"      checkArgument(SPECIAL_CHARACTER_PATTERN.matcher(newPassword).find(), \"Password must contain at least one special character\");\n    } catch (IllegalArgumentException e) {\n      throw new PasswordException(e.getMessage());\n    }\n  }\n\n  private static String getParamOrThrow(HttpRequest request, String key) throws PasswordException {\n    String value = request.getParameter(key);\n    if (isNullOrEmpty(value)) {\n      throw new PasswordException(format(MSG_PARAMETER_MISSING, key));\n    }\n    return value;\n  }\n\n  private void checkPreviousPassword(DbSession dbSession, UserDto user, String password) throws PasswordException {\n    try {\n      localAuthentication.authenticate(dbSession, user, password, AuthenticationEvent.Method.BASIC);\n    } catch (AuthenticationException ex) {\n      throw new PasswordException(OLD_PASSWORD_INCORRECT, \"Incorrect password\");\n    }\n  }\n\n  private static void checkNewPasswordSameAsOld(String newPassword, String previousPassword) throws PasswordException {\n    if (previousPassword.equals(newPassword)) {\n      throw new PasswordException(NEW_PASSWORD_SAME_AS_OLD, \"Password must be different from old password\");\n    }\n  }\n\n  private UserDto getUserOrThrow(DbSession dbSession, String login) {\n    UserDto user = dbClient.userDao().selectByLogin(dbSession, login);\n    if (user == null || !user.isActive()) {\n      throw new NotFoundException(format(\"User with login '%s' has not been found\", login));\n    }\n    return user;\n  }\n\n  private void deleteTokensAndRefreshSession(HttpRequest request, HttpResponse response, DbSession dbSession, UserDto user) {","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java#L175-L211","documentation":"checkPreviousPassword authenticates the user with the supplied previous password via localAuthentication.authenticate; any AuthenticationException is converted into a PasswordException with code old_password_incorrect and message 'Incorrect password'. This prevents changing a password without knowing the current one.","triggerScenarios":"POST api/users/change_password where previous_password does not match the user's current local password (including after the password was already changed elsewhere).","commonSituations":"Stale cached password in a form; password changed by SSO/admin meanwhile; users with external (non-local) authentication whose local verification always fails; pasting the new password into the old-password field.","solutions":["Re-enter the correct current password","Reset the password via admin (api/users/change_password as admin bypasses, or password reset flow) if the old one is lost","Verify the user is a local account, not delegating authentication to an external identity provider"],"exampleFix":"// before\nPOST ...?previous_password=TypoPass&new_password=X\n// after\nPOST ...?previous_password=CorrectCurrentPass&new_password=X","handlingStrategy":"try-catch","validationCode":"// no safe pre-check without authenticating; at minimum confirm the account is local\nconst user = await getUser(login);\nif (user.externalIdentity) throw new Error('Non-local users cannot verify previous password locally');","typeGuard":null,"tryCatchPattern":"try { await changePassword(login, oldPw, newPw); } catch (e) { if (e.code === 'old_password_incorrect') { rePromptForCurrentPassword(); return; } throw e; }","preventionTips":["Warn users with stale sessions that their password may have changed elsewhere","Detect externally-managed accounts and route to IdP password reset instead","Never autofill the previous-password field"],"tags":["password","authentication","users","api"],"backgroundTag":"authentication-failed","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}