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
- Initialize the constructor input with a default containing providers: pass ['providers' => [...defaults]] when the stored settings are null.
- Call MfaOrgSettings::getOrCreate() or equivalent factory that falls back to defaults instead of raw new MfaOrgSettings(null).
- Save valid MFA org settings via the admin MFA settings endpoint so the database record exists.
- 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
- Use factory methods (getOrCreate) that supply defaults instead of raw construction
- Never pass raw null DB rows into the constructor — merge with default providers
- Ensure OrganizationSettings record for MFA exists before building org settings
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
- An authentication token state is required.
- Could not create MFA verified cookie.
- Could not enable Duo MFA provider.
- Could not enable Duo MFA provider.
- Could not login using Duo MFA provider.
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)