laravel/framework · critical · RuntimeException
Unsupported cipher or incorrect key length. Supported…
Error message
Unsupported cipher or incorrect key length. Supported ciphers are: {$ciphers}. What it means
Encrypter::__construct validates the key+cipher pair via Encrypter::supported(), which checks that the cipher is one of aes-128-cbc / aes-256-cbc / aes-128-gcm / aes-256-gcm AND that mb_strlen($key) matches the required byte size (16 or 32). If either fails, supported() returns false and the constructor throws. This is usually hit at application boot when APP_KEY and the configured cipher disagree.
Solutions
- Regenerate the key with the matching cipher: php artisan key:generate --cipher=aes-256-cbc (or whichever your config uses).
- Make config('app.cipher') match the key length: 16-byte key → aes-128-*, 32-byte key → aes-256-*.
- Verify the key is the raw decoded bytes the Encrypter expects (Laravel's APP_KEY is base64-Encoded, decoded automatically by KeyGuesser/the framework).
- If constructing the Encrypter manually, ensure mb_strlen($key, '8bit') equals 16 or 32 before calling new Encrypter($key, $cipher).
Example fix
// before // .env: APP_KEY=base64:shortKey (decodes to 16 bytes) // config/app.php: 'cipher' => 'aes-256-cbc', // after (align cipher to key) // .env: APP_KEY=base64:shortKey // config/app.php: 'cipher' => 'aes-128-cbc', // or regenerate a 32-byte key // $ php artisan key:generate --cipher=aes-256-cbc
Defensive patterns
Strategy: validation
Validate before calling
use Illuminate\Encryption\Encrypter;
$key = (string) config('app.key');
$cipher = config('app.cipher', 'aes-128-cbc');
if (! Encrypter::supported($key, $cipher)) {
throw new RuntimeException('APP_KEY length does not match cipher '.$cipher);
}
new Encrypter($key, $cipher); Type guard
function keyMatchesCipher(string $key, string $cipher): bool {
return \Illuminate\Encryption\Encrypter::supported($key, $cipher);
} Prevention
- Keep APP_KEY and config('app.cipher') consistent across all environments.
- After a key rotation, regenerate using php artisan key:generate --cipher=<your cipher>.
- Verify key byte length (16 for aes-128-*, 32 for aes-256-*) before booting.
When it happens
Trigger: Booting the app with APP_KEY set to a value whose length does not match the configured cipher (e.g. a 16-byte key with 'aes-256-cbc'); setting an invalid cipher string in config/app.php; passing a custom key/cipher to new Encrypter() that violates the size map.
Common situations: Generating APP_KEY on one project (32-char base64 → 32 raw bytes after decode for aes-256-cbc) and copying it to a project configured for aes-128-cbc; mis-typing the cipher; older Laravel cipher 'aes-256-cbc' vs newer 'aes-128-gcm' mismatch after an upgrade; using a raw hex key of the wrong length.
Related errors
- Could not decrypt the data.
- Could not encrypt the data.
- The MAC is invalid.
- Could not verify the hashed value's configuration.
- The payload is invalid.
AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11).
Data as JSON: /api/errors/04febb9eb3335147.
Report an issue: GitHub.
Appendix: source
Thrown at src/Illuminate/Encryption/Encrypter.php:61
'aes-256-gcm' => ['size' => 32, 'aead' => true],
];
/**
* Create a new encrypter instance.
*
* @param string $key
* @param string $cipher
*
* @throws \RuntimeException
*/
public function __construct(#[\SensitiveParameter] $key, $cipher = 'aes-128-cbc')
{
$key = (string) $key;
if (! static::supported($key, $cipher)) {
$ciphers = implode(', ', array_keys(self::$supportedCiphers));
throw new RuntimeException("Unsupported cipher or incorrect key length. Supported ciphers are: {$ciphers}.");
}
$this->key = $key;
$this->cipher = $cipher;
}
/**
* Determine if the given key and cipher combination is valid.
*
* @param string $key
* @param string $cipher
* @return bool
*/
public static function supported(#[\SensitiveParameter] $key, $cipher)
{
if (! isset(self::$supportedCiphers[strtolower($cipher)])) {
return false;
}View on GitHub (pinned to e0f6eb3518)