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

  1. Stop passing the $tag argument when decrypting with a CBC cipher, or pass null.
  2. Align both ends on an AEAD cipher (set APP_CIPHER=aes-256-gcm) if tag-based authentication is required.
  3. 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

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


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 bool

View on GitHub (pinned to e0f6eb3518)