{"record":{"id":"36a0f3c4a7f8fa32","repo":"SonarSource/sonarqube","slug":"s","errorCode":null,"errorMessage":"%s","messagePattern":"%s","errorType":"validation","errorClass":"PasswordException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java","lineNumber":177,"sourceCode":"      writeJsonResponse(badRequestException.getMessage(), response);\n      LOG.debug(badRequestException.getMessage(), badRequestException);\n    } catch (PasswordException passwordException) {\n      LOG.debug(passwordException.getMessage(), passwordException);\n      setResponseStatus(response, HTTP_BAD_REQUEST);\n      String message = passwordException.getPasswordMessage().map(pm -> pm.key).orElseGet(passwordException::getMessage);\n      writeJsonResponse(message, response);\n    }\n  }\n\n  private static void assertPasswordFormatIsValid(String newPassword) throws PasswordException {\n    try {\n      checkArgument(newPassword.length() >= MIN_PASSWORD_LENGTH, \"Password must be at least %s characters long\", MIN_PASSWORD_LENGTH);\n      checkArgument(UPPERCASE_PATTERN.matcher(newPassword).find(), \"Password must contain at least one uppercase character\");\n      checkArgument(LOWERCASE_PATTERN.matcher(newPassword).find(), \"Password must contain at least one lowercase character\");\n      checkArgument(DIGIT_PATTERN.matcher(newPassword).find(), \"Password must contain at least one digit\");\n      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  }","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java#L159-L195","documentation":"ChangePasswordAction.assertPasswordFormatIsValid enforces the configured password policy: minimum length plus at least one uppercase, one lowercase, one digit, and one special character. Each failing checkArgument's message is caught and rethrown as a PasswordException carrying the reason, returned to the caller (HTTP 400 with the specific policy message).","triggerScenarios":"POST api/users/change_password (or api/users/change_password for self) where the new_password parameter violates any rule: too short, or missing uppercase/lowercase/digit/special character.","commonSituations":"Automation generating passwords with limited character sets; UIs with older/weaker validation than the server; users choosing passwords below MIN_PASSWORD_LENGTH.","solutions":["Generate a password satisfying all rules (length >= MIN_PASSWORD_LENGTH, upper+lower+digit+special)","Read the PasswordException message to see which specific rule failed","Update client-side validation to mirror the server policy"],"exampleFix":"// before\nnewPassword = \"abc123\"                  // no uppercase/special\n// after\nnewPassword = \"Abc123!xyz\"             // satisfies all rules","handlingStrategy":"validation","validationCode":"function meetsPolicy(p) {\n  return p.length >= 8 && /[A-Z]/.test(p) && /[a-z]/.test(p) && /\\d/.test(p) && /[^A-Za-z0-9]/.test(p);\n}\nif (!meetsPolicy(newPassword)) throw new Error('Password violates policy');","typeGuard":null,"tryCatchPattern":"try { await changePassword(login, old, newPw); } catch (e) { if (e instanceof PasswordException && /Password must/.test(e.message)) { promptUserWithRule(e.message); } else throw e; }","preventionTips":["Mirror the server password policy (length, upper, lower, digit, special) in client validation","Use a password generator that guarantees character-class coverage","Surface the specific rule from the error message to end users"],"tags":["password","validation","users","policy"],"backgroundTag":"invalid-argument-format","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"}