laravel/framework · error · DecryptException
Unable to use tag because the cipher algorithm does not…
Error message
Unable to use tag because the cipher algorithm does not support AEAD.
What it means
Thrown by Encrypter::ensureTagIsValid() when the configured cipher is non-AEAD (aes-128-cbc / aes-256-cbc) but a string tag was supplied to decryption. CBC algorithms cannot use an authentication tag, so passing one indicates a caller/API mismatch. Laravel refuses to silently ignore the tag because mixing cipher modes would be insecure.
Solutions
- Stop passing the $tag argument when decrypting with a CBC cipher, or pass null.
- Align both ends on an AEAD cipher (set APP_CIPHER=aes-256-gcm) if tag-based authentication is required.
- Audit Encrypter construction to confirm the cipher matches the producer of the payload.
Example fix
// before: CBC cipher configured but tag supplied $plain = $encrypter->decrypt($payload, true, $tag); // after: do not pass a tag for non-AEAD ciphers $plain = $encrypter->decrypt($payload);
Defensive patterns
Strategy: validation
Validate before calling
$cipher = strtolower(config('app.cipher'));
$aead = in_array($cipher, ['aes-128-gcm','aes-256-gcm'], true);
if (! $aead && $tag !== null) {
throw new InvalidArgumentException('Tag provided but cipher is non-AEAD.');
} Type guard
function supportsAead(string $cipher): bool {
return in_array(strtolower($cipher), ['aes-128-gcm','aes-256-gcm'], true);
} Try / catch
use Illuminate\Contracts\Encryption\DecryptException;
try {
$plain = $encrypter->decrypt($payload, true, $aead ? $tag : null);
} catch (DecryptException $e) {
report($e);
return null;
} Prevention
- Decide once whether to use AEAD and apply it everywhere.
- Do not pass $tag by default; pass it only when cipher is AEAD.
- Keep APP_CIPHER consistent across environments.
- Document the cipher choice in your security runbook.
When it happens
Trigger: Calling Encrypter::decrypt($payload, $deserialize = true, $tag = '...') (or decryptString with a tag) while $this->cipher resolves to one of the CBC entries in $supportedCiphers where 'aead' is false.
Common situations: Code written against an AES-GCM deployment is reused on an environment whose APP_CIPHER is aes-256-cbc; downgrading cipher for compatibility while still forwarding a tag; copying example code that always passes a tag.
Related errors
- Could not decrypt the data.
- Could not encrypt the data.
- The MAC is invalid.
- The payload is invalid.
- The provided class must extend…
AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11).
Data as JSON: /api/errors/c340a1e9193de825.
Report an issue: GitHub.
Appendix: source
Thrown at src/Illuminate/Encryption/Encrypter.php:324
);
}
/**
* Ensure the given tag is a valid tag given the selected cipher.
*
* @param string $tag
* @return void
*
* @throws \Illuminate\Contracts\Encryption\DecryptException
*/
protected function ensureTagIsValid($tag)
{
if (self::$supportedCiphers[strtolower($this->cipher)]['aead'] && strlen($tag) !== 16) {
throw new DecryptException('Could not decrypt the data.');
}
if (! self::$supportedCiphers[strtolower($this->cipher)]['aead'] && is_string($tag)) {
throw new DecryptException('Unable to use tag because the cipher algorithm does not support AEAD.');
}
}
/**
* Determine if we should validate the MAC while decrypting.
*
* @return bool
*/
protected function shouldValidateMac()
{
return ! self::$supportedCiphers[strtolower($this->cipher)]['aead'];
}
/**
* Determine if the given value appears to be encrypted by this encrypter.
*
* @param mixed $value
* @return boolView on GitHub (pinned to e0f6eb3518)