passbolt/passbolt_api · error · InternalErrorException

Invalid MFA org settings.

Error message

Invalid MFA org settings.

What it means

MfaOrgSettings::__construct() requires a merged settings array (from config + database) containing the 'providers' key. It throws InternalErrorException when $settings is null or lacks PROVIDERS — the org-level MFA settings are missing or malformed, which the class treats as a server-side invariant violation rather than a user error.

Solutions

  1. Initialize the constructor input with a default containing providers: pass ['providers' => [...defaults]] when the stored settings are null.
  2. Call MfaOrgSettings::getOrCreate() or equivalent factory that falls back to defaults instead of raw new MfaOrgSettings(null).
  3. Save valid MFA org settings via the admin MFA settings endpoint so the database record exists.
  4. Catch InternalErrorException in higher-level service code and fall back to default provider lists.

Example fix

// before
$orgSettings = new MfaOrgSettings($dbSettings); // $dbSettings may be null
// after
$orgSettings = new MfaOrgSettings($dbSettings ?? ['providers' => MfaSettings::PROVIDERS_ALLOWED]);
Defensive patterns

Strategy: validation

Validate before calling

$settings = $settings ?? [];
if (!isset($settings[MfaSettings::PROVIDERS])) {
    $settings[MfaSettings::PROVIDERS] = MfaSettings::PROVIDERS_ALLOWED;
}
$orgSettings = new MfaOrgSettings($settings);

Type guard

$isValid = is_array($settings) && array_key_exists(MfaSettings::PROVIDERS, $settings);

Try / catch

try { $s = new MfaOrgSettings($raw); } catch (\Cake\Http\Exception\InternalErrorException $e) { $s = new MfaOrgSettings(['providers' => []]); }

Prevention

When it happens

Trigger: Constructing MfaOrgSettings with null (no org settings stored in OrganizationSettings table) or an array without the 'providers' key; calling MfaOrgSettings::get() when no MFA org settings were ever saved.

Common situations: Fresh passbolt instance where admins never configured MFA org settings; code paths reading org settings before the MFA settings page was saved; database row missing after migration; manually deleted OrganizationSettings record; passing unmerged config arrays in tests.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at plugins/PassboltCe/MultiFactorAuthentication/src/Utility/MfaOrgSettings.php:65

    /**
     * @var \App\Model\Table\OrganizationSettingsTable
     */
    protected OrganizationSettingsTable $OrganizationSettings;

    /**
     * @var array|null
     */
    protected ?array $settings = null;

    /**
     * MfaOrgSettings constructor.
     *
     * @param array|null $settings merged settings from configure and database
     */
    public function __construct(?array $settings = null)
    {
        if (!isset($settings) || !isset($settings[MfaSettings::PROVIDERS])) {
            throw new InternalErrorException('Invalid MFA org settings.');
        }
        $settings[MfaSettings::PROVIDERS] = $this->formatProviders($settings[MfaSettings::PROVIDERS]);
        $this->settings = $settings;
        $this->OrganizationSettings = TableRegistry::getTableLocator()->get('OrganizationSettings');
    }

    /**
     * Format Providers
     *
     * We accept both format ['providers' => ['totp' => true ]] and ['providers' => ['totp']]
     * This function format the former to the latter to ensure consistent format
     *
     * @param array $providers see above
     * @return array
     */
    private function formatProviders(array $providers): array
    {
        $result = $providers;

View on GitHub (pinned to 31c1bbc10f)