phacility/phabricator · error · Exception
Hasher "%s" may produce hashes which are too long to fit in
Error message
Hasher "%s" may produce hashes which are too long to fit in storage. %d characters are available, but its hashes may be up to %d characters in length.
What it means
Password hashes are stored as 'name:hash' strings in a fixed-size storage column, capped by PhabricatorPasswordHasher::MAXIMUM_STORAGE_SIZE (128 characters). When hasher classes are discovered (getAllHashers), each one is checked: strlen(getHashName()) + getHashLength() + 1 must fit within 128. A hasher that could exceed the cap is rejected at discovery time so a password can never be hashed into something un-storable.
Source
Thrown at src/infrastructure/util/password/PhabricatorPasswordHasher.php:227
* actually be used (for example, a required extension is missing).
*
* @return list<PhabricatorPasswordHasher> Hasher objects.
* @task hashing
*/
public static function getAllHashers() {
$objects = id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getHashName')
->execute();
foreach ($objects as $object) {
$name = $object->getHashName();
$potential_length = strlen($name) + $object->getHashLength() + 1;
$maximum_length = self::MAXIMUM_STORAGE_SIZE;
if ($potential_length > $maximum_length) {
throw new Exception(
pht(
'Hasher "%s" may produce hashes which are too long to fit in '.
'storage. %d characters are available, but its hashes may be '.
'up to %d characters in length.',
$name,
$maximum_length,
$potential_length));
}
}
return $objects;
}
/**
* Get all usable password hashers. This may include hashers which are
* not desirable or advisable.
*View on GitHub (pinned to 5720a38cfe)
Solutions
- Shorten getHashName() to a compact unique identifier (e.g. 'xargon2') and keep parameters inside the hash body only if the total still fits.
- Reduce getHashLength() by encoding the digest more compactly (base64 instead of hex halves the length) so name + ':' + digest stays under 128.
- If the format genuinely cannot fit in 128 characters, the algorithm is not usable with Phabricator's storage schema — pick a shorter representation.
- Add a unit test asserting strlen($name) + $hasher->getHashLength() + 1 <= PhabricatorPasswordHasher::MAXIMUM_STORAGE_SIZE.
Example fix
// before
public function getHashName() {
return 'argon2id-v=19-m=65536-t=4-p=1'; // 26 chars + long digest
}
public function getHashLength() {
return 512; // hex-encoded digest -> total exceeds 128
}
// after
public function getHashName() {
return 'xargon2id'; // parameters live in the digest, not the name
}
public function getHashLength() {
return 64; // raw 32-byte digest, base64url-encoded
} Defensive patterns
Strategy: validation
Validate before calling
// Check a custom hasher fits storage before registering it:
$name = $hasher->getHashName();
$length = strlen($name) + $hasher->getHashLength() + 1;
if ($length > PhabricatorPasswordHasher::MAXIMUM_STORAGE_SIZE) {
throw new Exception(
pht('Hasher %s needs %d chars but only %d are available.',
$name, $length, PhabricatorPasswordHasher::MAXIMUM_STORAGE_SIZE));
} Prevention
- Keep getHashName() short (a few characters) — it is an identifier, not a parameter string.
- Encode digests compactly (base64 not hex) and return the true maximum length from getHashLength().
- Add a unit test for the 128-character budget so regressions fail in CI, not in production.
When it happens
Trigger: Registering a custom PhabricatorPasswordHasher subclass whose getHashName() plus getHashLength() totals more than 127 characters — e.g. a long algorithm identifier like 'super-argon2id-v19-m=65536,t=4,p=1' combined with a long raw or hex-encoded hash. The exception is thrown while enumerating hashers, which happens during password operations and authentication setup.
Common situations: Writing a custom hasher that returns the full algorithm parameters in getHashName(); returning getHashLength() as the base64/hex length of the encoded output when it should be the trimmed length; wrapping an external library that emits very long composite hashes.
Related errors
- Service "%s" is unrecognized, restricted, or you do not have
- When creating a new Almanac interface via the Conduit API, y
- Device "%s" is unrecognized, restricted, or you do not have
- Interfaces must have a unique combination of network, device
- Another namespace with this name already exists. Each namesp
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/905652ff758bf81d.
Report an issue: GitHub.