{"record":{"id":"e7544600fb500dfb","repo":"phacility/phabricator","slug":"there-are-no-password-hashers-available-which-are","errorCode":null,"errorMessage":"There are no password hashers available which are usable for new passwords.","messagePattern":"There are no password hashers available which are usable for new passwords\\.","errorType":"exception","errorClass":"PhabricatorPasswordHasherUnavailableException","httpStatus":null,"severity":"error","filePath":"src/infrastructure/util/password/PhabricatorPasswordHasher.php","lineNumber":272,"sourceCode":"      }\n    }\n    return $hashers;\n  }\n\n\n  /**\n   * Get the best (strongest) available hasher.\n   *\n   * @return PhabricatorPasswordHasher Best hasher.\n   * @task hashing\n   */\n  public static function getBestHasher() {\n    $hashers = self::getAllUsableHashers();\n    $hashers = msort($hashers, 'getStrength');\n\n    $hasher = last($hashers);\n    if (!$hasher) {\n      throw new PhabricatorPasswordHasherUnavailableException(\n        pht(\n          'There are no password hashers available which are usable for '.\n          'new passwords.'));\n    }\n\n    return $hasher;\n  }\n\n\n  /**\n   * Get the hasher for a given stored hash.\n   *\n   * @return PhabricatorPasswordHasher Corresponding hasher.\n   * @task hashing\n   */\n  public static function getHasherForHash(PhutilOpaqueEnvelope $hash) {\n    $info = self::parseHashFromStorage($hash);\n    $name = $info['name'];","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/util/password/PhabricatorPasswordHasher.php#L254-L290","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","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'));\\\"'.","If a custom hasher registry or configuration excludes hashers, re-enable at least one usable hasher.","Until fixed, disable the password auth provider so users get a clear 'provider unavailable' message instead of an exception."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Detect the broken-hasher environment before users hit it (e.g. at provider configuration time):\ntry {\n  PhabricatorPasswordHasher::getBestHasher();\n  $password_auth_ok = true;\n} catch (PhabricatorPasswordHasherUnavailableException $e) {\n  $password_auth_ok = false; // show setup instructions, keep other providers up\n}","typeGuard":null,"tryCatchPattern":"// Catch the specific exception type; it exists precisely so callers can react:\ntry {\n  $hasher = PhabricatorPasswordHasher::getBestHasher();\n  $hash = $hasher->getPasswordHash($envelope);\n} catch (PhabricatorPasswordHasherUnavailableException $e) {\n  // $e->getMessage() plus each hasher's getInstallInstructions() tell the admin what to install\n  return $this->newDialog()->setTitle(pht('No Password Hasher Available'))\n    ->appendParagraph($e->getMessage());\n}","preventionTips":["Verify 'php -m' includes the hash extension (and crypt() works) in your provisioning scripts and container images.","Probe getBestHasher() in a health/CI check so a stripped PHP build is caught before deploy.","Do not rely solely on password auth; keep a second auth provider enabled so users are never locked out."],"tags":["phabricator","password-hashing","php-extensions","environment"],"backgroundTag":"missing-php-extension","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}