SonarSource/sonarqube · error · PasswordException

The ' ' parameter is missing

Error message

The '%s' parameter is missing

What it means

getParamOrThrow converts a missing/empty required parameter (login, previousPassword, or newPassword) into a PasswordException with MSG_PARAMETER_MISSING, so change-password callers get a consistent 400-style error naming the missing parameter instead of an NPE downstream.

Solutions

  1. Provide all required parameters: login, previous_password, new_password
  2. Check for empty-string values in the client before sending
  3. Fix parameter name spelling to match the API contract

Example fix

// before
POST /api/users/change_password?login=jdoe&new_password=X   // missing previous_password
// after
POST /api/users/change_password?login=jdoe&previous_password=OLD&new_password=X
Defensive patterns

Strategy: validation

Validate before calling

for (const [k, v] of {login, previous_password, new_password}) {
  if (v == null || v === '') throw new Error(`Missing required parameter: ${k}`);
}

Type guard

function hasValue(v) { return typeof v === 'string' && v.length > 0; }

Try / catch

try { await changePassword(params); } catch (e) { if (/parameter is missing/.test(e.message)) { const missing = e.message.match(/'(.*)'/)[1]; throw new Error(`Provide ${missing} before retrying`); } throw e; }

Prevention

When it happens

Trigger: POST api/users/change_password without login, previous_password, or new_password, or with any of them set to an empty string.

Common situations: Forms/clients omitting the old-password field when the caller is an administrator assuming it is optional; empty request bodies; parameter name typos in scripts.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/c28200fe457f8700. Report an issue: GitHub.

Appendix: source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java:184

    }
  }

  private static void assertPasswordFormatIsValid(String newPassword) throws PasswordException {
    try {
      checkArgument(newPassword.length() >= MIN_PASSWORD_LENGTH, "Password must be at least %s characters long", MIN_PASSWORD_LENGTH);
      checkArgument(UPPERCASE_PATTERN.matcher(newPassword).find(), "Password must contain at least one uppercase character");
      checkArgument(LOWERCASE_PATTERN.matcher(newPassword).find(), "Password must contain at least one lowercase character");
      checkArgument(DIGIT_PATTERN.matcher(newPassword).find(), "Password must contain at least one digit");
      checkArgument(SPECIAL_CHARACTER_PATTERN.matcher(newPassword).find(), "Password must contain at least one special character");
    } catch (IllegalArgumentException e) {
      throw new PasswordException(e.getMessage());
    }
  }

  private static String getParamOrThrow(HttpRequest request, String key) throws PasswordException {
    String value = request.getParameter(key);
    if (isNullOrEmpty(value)) {
      throw new PasswordException(format(MSG_PARAMETER_MISSING, key));
    }
    return value;
  }

  private void checkPreviousPassword(DbSession dbSession, UserDto user, String password) throws PasswordException {
    try {
      localAuthentication.authenticate(dbSession, user, password, AuthenticationEvent.Method.BASIC);
    } catch (AuthenticationException ex) {
      throw new PasswordException(OLD_PASSWORD_INCORRECT, "Incorrect password");
    }
  }

  private static void checkNewPasswordSameAsOld(String newPassword, String previousPassword) throws PasswordException {
    if (previousPassword.equals(newPassword)) {
      throw new PasswordException(NEW_PASSWORD_SAME_AS_OLD, "Password must be different from old password");
    }
  }

View on GitHub (pinned to 184c821202)