passbolt/passbolt_api · error · RecordNotFoundException

No MFA provider set.

Error message

No MFA provider set.

What it means

MfaAccountSettings::getProviders() returns the list of MFA providers enabled for a user account. It throws RecordNotFoundException when the internal settings array has no 'providers' key, meaning the account has no MFA configuration stored (or an empty/incomplete settings array was constructed).

Solutions

  1. Check the user has MFA enabled before calling: guard with MfaAccountSettings retrieval or a settings isset/empty check.
  2. Wrap the call in try/catch on \Cake\Datasource\Exception\RecordNotFoundException and treat the user as having no providers.
  3. Verify the account settings payload passed to the constructor actually contains the 'providers' key.
  4. If enrollment was expected, have the user complete MFA setup so settings get persisted.

Example fix

// before
$providers = $mfaAccountSettings->getEnabledProviders();
// after
try {
    $providers = $mfaAccountSettings->getEnabledProviders();
} catch (\Cake\Datasource\Exception\RecordNotFoundException $e) {
    $providers = [];
}
Defensive patterns

Strategy: try-catch

Validate before calling

$providers = [];
try {
    $providers = $mfaAccountSettings->getEnabledProviders();
} catch (\Cake\Datasource\Exception\RecordNotFoundException $e) {}

Type guard

$hasProviders = isset($mfaAccountSettings->toArray()[MfaSettings::PROVIDERS]);

Try / catch

try { $providers = $s->getEnabledProviders(); } catch (\Cake\Datasource\Exception\RecordNotFoundException $e) { $providers = []; }

Prevention

When it happens

Trigger: Calling getEnabledProviders() or disableProvider() on a MfaAccountSettings object whose settings array lacks the PROVIDERS key — e.g. built from an empty or partial account settings payload for a user who never enabled MFA.

Common situations: Checking a user's MFA status before they ever enrolled; account settings stored in OrganizationSettings are null/empty; after a data wipe or migration that dropped the mfa_accounts_settings payload; code paths that skip the isProviderEnabled/hasProviders pre-check.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/1cae1bb17f1eded2. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/MultiFactorAuthentication/src/Utility/MfaAccountSettings.php:141

     * Return MfaSettings as JSON object
     *
     * @return string|false
     */
    public function toJson(): string|false
    {
        return json_encode($this->settings);
    }

    /**
     * Return all providers
     *
     * @throws \Cake\Datasource\Exception\RecordNotFoundException if there is no provider set
     * @return array list of providers
     */
    protected function getProviders(): array
    {
        if (!isset($this->settings[self::PROVIDERS])) {
            throw new RecordNotFoundException(__('No MFA provider set.'));
        }

        return $this->settings[self::PROVIDERS];
    }

    /**
     * Get an array of provider name that are enabled and verified for this user
     *
     * @throws \Cake\Datasource\Exception\RecordNotFoundException
     * @return array
     */
    public function getEnabledProviders(): array
    {
        $result = [];
        $providers = $this->getProviders();
        foreach ($providers as $provider) {
            if ($this->isProviderReady($provider)) {
                $result[] = $provider;

View on GitHub (pinned to 31c1bbc10f)