How to Fix "The MAC is invalid." Exception in Spatie Permission

In many of my Laravel projects, I use Spatie's Permission package alongside encrypted settings to keep sensitive data safe from breaches. However, this can create an issue when you copy production data to a local or staging environment. Since encryption keys differ between environments, attempting to decrypt the settings can result in the following exception: The MAC is invalid. This error typically occurs because Laravel is trying to decrypt data that was encrypted with a different application key (APP_KEY). To solve this, I wrote a custom Artisan command that resets all encrypted setting values to an empty string. The Solution: Reset All Encrypted Setting Values Here’s the command: namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\File; use Spatie\LaravelSettings\SettingsRepositories\SettingsRepository; use Spatie\LaravelSettings\Support\Crypto; class EmptyAllEncryptedSettingKeysCommand extends Command { protected $signature = 'app:empty-all-encrypted-setting-keys'; protected $description = 'Reset all encrypted setting values to an empty string.'; public function handle(): int { $settingsFolder = app_path('Settings'); $files = File::allFiles($settingsFolder); $settingsRepository = app(SettingsRepository::class); foreach ($files as $file) { $relativePath = $file->getRelativePathname(); $settingsClass = str_replace( ['/', '.php'], ['\\', ''], 'App\\Settings\\' . $relativePath ); if (class_exists($settingsClass) && method_exists($settingsClass, 'encrypted')) { foreach ($settingsClass::encrypted() as $key) { $settingsRepository->updatePropertiesPayload( $settingsClass::group(), [$key => Crypto::encrypt('')] ); } } } $this->info('All encrypted setting values have been reset.'); return Command::SUCCESS; } } What Does This Command Do? It scans all classes under App\Settings\*. For each class, it checks if it has an encrypted() method (used to declare encrypted properties). It loops through those encrypted keys and replaces their values with an empty encrypted string using Spatie\LaravelSettings. Why This Helps When you clone your production database to another environment (e.g., staging or local), any encrypted values cannot be decrypted unless the encryption key (APP_KEY) matches. Instead of trying to sync keys across environments (which is insecure), it's often safer and easier to just reset encrypted values. Running this command prevents "The MAC is invalid." exception and allows you to work with the rest of the settings normally.

May 5, 2025 - 19:27
 0
How to Fix "The MAC is invalid." Exception in Spatie Permission

In many of my Laravel projects, I use Spatie's Permission package alongside encrypted settings to keep sensitive data safe from breaches. However, this can create an issue when you copy production data to a local or staging environment. Since encryption keys differ between environments, attempting to decrypt the settings can result in the following exception:

The MAC is invalid.

This error typically occurs because Laravel is trying to decrypt data that was encrypted with a different application key (APP_KEY). To solve this, I wrote a custom Artisan command that resets all encrypted setting values to an empty string.

The Solution: Reset All Encrypted Setting Values

Here’s the command:

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Spatie\LaravelSettings\SettingsRepositories\SettingsRepository;
use Spatie\LaravelSettings\Support\Crypto;

class EmptyAllEncryptedSettingKeysCommand extends Command
{
    protected $signature = 'app:empty-all-encrypted-setting-keys';
    protected $description = 'Reset all encrypted setting values to an empty string.';

    public function handle(): int
    {
        $settingsFolder = app_path('Settings');
        $files = File::allFiles($settingsFolder);
        $settingsRepository = app(SettingsRepository::class);

        foreach ($files as $file) {
            $relativePath = $file->getRelativePathname();

            $settingsClass = str_replace(
                ['/', '.php'],
                ['\\', ''],
                'App\\Settings\\' . $relativePath
            );

            if (class_exists($settingsClass) && method_exists($settingsClass, 'encrypted')) {
                foreach ($settingsClass::encrypted() as $key) {
                    $settingsRepository->updatePropertiesPayload(
                        $settingsClass::group(),
                        [$key => Crypto::encrypt('')]
                    );
                }
            }
        }

        $this->info('All encrypted setting values have been reset.');
        return Command::SUCCESS;
    }
}

What Does This Command Do?

  • It scans all classes under App\Settings\*.
  • For each class, it checks if it has an encrypted() method (used to declare encrypted properties).
  • It loops through those encrypted keys and replaces their values with an empty encrypted string using Spatie\LaravelSettings.

Why This Helps

When you clone your production database to another environment (e.g., staging or local), any encrypted values cannot be decrypted unless the encryption key (APP_KEY) matches. Instead of trying to sync keys across environments (which is insecure), it's often safer and easier to just reset encrypted values.

Running this command prevents "The MAC is invalid." exception and allows you to work with the rest of the settings normally.