phacility/phabricator · error · PhabricatorPasswordHasherUnavailableException

There are no password hashers available which are usable for

Error message

There are no password hashers available which are usable for new passwords.

What it means

When Phabricator needs to hash a new password (account creation, password change, password auth provider), getBestHasher() picks the strongest hasher whose canHashPasswords() is true and which passes a self-test. If no hasher qualifies, it throws the dedicated PhabricatorPasswordHasherUnavailableException — almost always an environment problem, such as PHP built without the hash/crypt capabilities the bundled hashers require.

Source

Thrown at src/infrastructure/util/password/PhabricatorPasswordHasher.php:272

      }
    }
    return $hashers;
  }


  /**
   * Get the best (strongest) available hasher.
   *
   * @return PhabricatorPasswordHasher Best hasher.
   * @task hashing
   */
  public static function getBestHasher() {
    $hashers = self::getAllUsableHashers();
    $hashers = msort($hashers, 'getStrength');

    $hasher = last($hashers);
    if (!$hasher) {
      throw new PhabricatorPasswordHasherUnavailableException(
        pht(
          'There are no password hashers available which are usable for '.
          'new passwords.'));
    }

    return $hasher;
  }


  /**
   * Get the hasher for a given stored hash.
   *
   * @return PhabricatorPasswordHasher Corresponding hasher.
   * @task hashing
   */
  public static function getHasherForHash(PhutilOpaqueEnvelope $hash) {
    $info = self::parseHashFromStorage($hash);
    $name = $info['name'];

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Check what PHP can do: 'php -m | grep -i hash' and inspect get_loaded_extensions(); install/enable the hash extension (often 'docker-php-ext-install hash' or the distro's php-hash package) and restart PHP-FPM.
  2. Verify with Phabricator's own tooling: 'bin/auth ssh-key' style checks aside, the simplest probe is 'php -r \"var_dump(function_exists('hash_hmac'), function_exists('crypt'));\"'.
  3. If a custom hasher registry or configuration excludes hashers, re-enable at least one usable hasher.
  4. Until fixed, disable the password auth provider so users get a clear 'provider unavailable' message instead of an exception.
Defensive patterns

Strategy: try-catch

Validate before calling

// Detect the broken-hasher environment before users hit it (e.g. at provider configuration time):
try {
  PhabricatorPasswordHasher::getBestHasher();
  $password_auth_ok = true;
} catch (PhabricatorPasswordHasherUnavailableException $e) {
  $password_auth_ok = false; // show setup instructions, keep other providers up
}

Try / catch

// Catch the specific exception type; it exists precisely so callers can react:
try {
  $hasher = PhabricatorPasswordHasher::getBestHasher();
  $hash = $hasher->getPasswordHash($envelope);
} catch (PhabricatorPasswordHasherUnavailableException $e) {
  // $e->getMessage() plus each hasher's getInstallInstructions() tell the admin what to install
  return $this->newDialog()->setTitle(pht('No Password Hasher Available'))
    ->appendParagraph($e->getMessage());
}

Prevention

When it happens

Trigger: Calling PhabricatorPasswordHasher::getBestHasher() (directly or via password registration/login flows) on a PHP installation where every hasher's canHashPasswords() returns false — e.g. PHP compiled without ext-hash (kills PBKDF2/hmac-based hashers) or a crypt() without modern algorithm support. Also occurs if configuration or custom hasher registrations disable everything.

Common situations: Minimal/container PHP images (e.g. 'php:*-alpine' variants) missing ext-hash or compiled without proper crypt support; PHP rebuilt with aggressive './configure' flags that dropped extensions; locking down the hasher list via configuration so no usable hasher remains.

Related errors


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