phacility/phabricator · warning · PhabricatorAuthPasswordException

The password and confirmation do not match.

Error message

The password and confirmation do not match.

What it means

The strict-comparison check in checkNewPassword(): when the raw password and raw confirmation differ (raw_password !== raw_confirm), both field errors are set to 'Invalid' (getPasswordError() and getConfirmError()), letting the UI mark both boxes. The comparison is byte-exact, not normalized.

Source

Thrown at src/applications/auth/engine/PhabricatorAuthPasswordEngine.php:99

          pht(
            'The selected password is too short. Passwords must be a minimum '.
            'of %s characters long.',
            new PhutilNumber($min_len)),
          pht('Too Short'));
      }
    }

    $raw_confirm = $confirm->openEnvelope();

    if (!strlen($raw_confirm)) {
      throw new PhabricatorAuthPasswordException(
        pht('You must confirm the selected password.'),
        null,
        pht('Required'));
    }

    if ($raw_password !== $raw_confirm) {
      throw new PhabricatorAuthPasswordException(
        pht('The password and confirmation do not match.'),
        pht('Invalid'),
        pht('Invalid'));
    }

    if (PhabricatorCommonPasswords::isCommonPassword($raw_password)) {
      throw new PhabricatorAuthPasswordException(
        pht(
          'The selected password is very weak: it is one of the most common '.
          'passwords in use. Choose a stronger password.'),
        pht('Very Weak'));
    }

    // If we're creating a brand new object (like registering a new user)
    // and it does not have a PHID yet, it isn't possible for it to have any
    // revoked passwords or colliding passwords either, so we can skip these
    // checks.

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Re-enter the password and confirmation so they match exactly (watch for stray spaces).
  2. In custom forms, compare the two raw values before submitting to give instant feedback.
  3. Catch PhabricatorAuthPasswordException and render both getPasswordError() and getConfirmError().

Example fix

// before: submit directly to the engine
$engine->checkNewPassword($password, $confirm);

// after: pre-compare to avoid the round trip
if ($password->openEnvelope() !== $confirm->openEnvelope()) {
  // flag both fields client-side before calling the engine
}
$engine->checkNewPassword($password, $confirm);
Defensive patterns

Strategy: validation

Validate before calling

// Cheap client-side pre-compare avoids the engine round trip
if ($password->openEnvelope() !== $confirm->openEnvelope()) {
  $e_password = pht('Invalid');
  $e_confirm = pht('Invalid');
  return $this->buildPasswordFormResponse($e_password, $e_confirm);
}

Try / catch

try {
  $engine->checkNewPassword($password, $confirm);
} catch (PhabricatorAuthPasswordException $ex) {
  if ($ex->getPasswordError() === pht('Invalid') && $ex->getConfirmError() === pht('Invalid')) {
    // mismatch: flag both fields
  }
}

Prevention

When it happens

Trigger: Any checkNewPassword() call where the two envelopes contain different strings - a typo in one field, trailing whitespace pasted into one box, or a mismatched caps-lock state.

Common situations: Users retyping rather than pasting; password managers inserting different entries into each field; leading/trailing space copied from a chat message; JavaScript-stripped whitespace on one field only.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/78c03f24d610baed. Report an issue: GitHub.