PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
Password exceeds 255 characters
Error message
Password exceeds 255 characters
What it means
Thrown by PasswordHasher::hashPassword() when the password exceeds MAX_PASSWORD_LENGTH (255 characters). The MS-OFFCRYPTO password-verifier derivation the class implements is only defined for strings up to 255 characters, so longer input is rejected outright rather than hashed.
Source
Thrown at src/PhpSpreadsheet/Shared/PasswordHasher.php:89
/**
* Create a password hash from a given string by a specific algorithm.
*
* 2.4.2.4 ISO Write Protection Method
*
* @see https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-offcrypto/1357ea58-646e-4483-92ef-95d718079d6f
*
* @param string $password Password to hash
* @param string $algorithm Hash algorithm used to compute the password hash value
* @param string $salt Pseudorandom base64-encoded string
* @param int $spinCount Number of times to iterate on a hash of a password
*
* @return string Hashed password
*/
public static function hashPassword(string $password, string $algorithm = '', string $salt = '', int $spinCount = 10000): string
{
if (strlen($password) > self::MAX_PASSWORD_LENGTH) {
throw new SpException('Password exceeds ' . self::MAX_PASSWORD_LENGTH . ' characters');
}
$phpAlgorithm = self::getAlgorithm($algorithm);
if (!$phpAlgorithm) {
return self::defaultHashPassword($password);
}
$saltValue = base64_decode($salt);
$encodedPassword = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8');
$hashValue = hash($phpAlgorithm, $saltValue . $encodedPassword, true);
for ($i = 0; $i < $spinCount; ++$i) {
$hashValue = hash($phpAlgorithm, $hashValue . pack('L', $i), true);
}
return base64_encode($hashValue);
}
}
View on GitHub (pinned to 65b080eef4)
Solutions
- Enforce a <= 255 cap in the UI/API that collects the protection password and explain the limit.
- If a longer secret is mandatory, hash/derive a <=255-byte value first (e.g. substr(sha1($secret), 0, 40)) and use that as the workbook password, documenting that the sheet password is now derived.
- Trim accidental whitespace/newlines from pasted input before the length check.
- Catch the exception and return a validation error rather than letting it bubble into a 500.
Example fix
// before
$hash = PasswordHasher::hashPassword($request->input('password'));
// Password exceeds 255 characters
// after
$password = trim((string) $request->input('password'));
if (strlen($password) > 255) {
throw new \InvalidArgumentException('Sheet protection password must be at most 255 characters.');
}
$hash = PasswordHasher::hashPassword($password); Defensive patterns
Strategy: validation
Validate before calling
define('SHEET_PASSWORD_MAX', 255);
$password = trim($password);
if (strlen($password) > SHEET_PASSWORD_MAX) {
throw new InvalidArgumentException(
sprintf('Sheet password too long: %d chars (max %d).', strlen($password), SHEET_PASSWORD_MAX)
);
} Type guard
function sheetPasswordCandidate(mixed $pw): ?string
{
return (is_string($pw) && strlen(trim($pw)) > 0 && strlen($pw) <= 255) ? $pw : null;
} Try / catch
try { $hash = PasswordHasher::hashPassword($password); }
catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
if (str_contains($e->getMessage(), 'exceeds')) {
// decide policy: reject, or derive a shorter password from the secret
throw new DomainException('Password must be at most 255 characters.', 0, $e);
}
throw $e;
} Prevention
- Cap sheet-protection passwords at 255 in the UI/API that collects them.
- If reusing long app secrets, derive a short workbook password instead of truncating silently.
- Watch for paste errors (multi-line text) — trim before measuring.
When it happens
Trigger: Calling hashPassword($password) with strlen($password) > 255 — e.g. hashing a passphrase, a generated token, or accidental input like pasted multi-line text or a whole array-as-string; also when reading user-supplied passwords for sheet protection without an upstream length cap.
Common situations: Applications that reuse login passphrases (arbitrary length) as sheet-protection passwords; unit tests using long random strings; user paste errors; feeding base64 blobs where a password belonged.
Related errors
- Unsupported password algorithm: $algorithmName
- Trend(): Number of elements in coordinate arrays do not matc
- Unsupported binary comparison operator
- Cloning the calculation engine is not allowed!
- Unsupported numeric binary operation
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/8b530df087ffa0b8.
Report an issue: GitHub.