passbolt/passbolt_api · error · CustomValidationException

Could not validate multi-factor authentication provider…

Error message

Could not validate multi-factor authentication provider configuration.

What it means

After validating each individual provider's configuration, MfaOrgSettings::validate() aggregates per-provider errors and throws CustomValidationException (with the error details as its second argument) if any provider failed. It signals that at least one provider's org-level configuration is invalid.

Solutions

  1. Inspect the exception's validation errors (its second argument) to identify which provider and field failed, fix those values, and resubmit.
  2. Run the provider form validation client-side or in the service before calling save().
  3. Verify each provider's config against the provider form rules: issuer format for totp, numeric clientId and non-empty secretKey for yubikey.
  4. Catch CustomValidationException and surface $e->getErrors() to the admin UI.
  5. exampleFixPlaceholder

Example fix

// before
try {
    $orgSettings->save($data);
} catch (\App\Error\Exception\CustomValidationException $e) {
    throw new InternalErrorException($e->getMessage());
}
// after
try {
    $orgSettings->save($data);
} catch (\App\Error\Exception\CustomValidationException $e) {
    throw new BadRequestException($e->getMessage(), 400, $e); // include $e->getErrors() in response
}
Defensive patterns

Strategy: try-catch

Try / catch

try { $orgSettings->save($data); } catch (\App\Error\Exception\CustomValidationException $e) { $errors = $e->getErrors(); /* surface per-provider errors to client */ }

Prevention

When it happens

Trigger: Calling validate()/save() where a per-provider form (e.g. MfaOrgSettingsTotpForm or yubikey form) fails validation — e.g. invalid TOTP issuer, missing/invalid yubikey clientId or secretKey format — populating $results with errors.

Common situations: Admin saving org MFA settings with a typo in provider config values; yubikey clientId/secretKey failing validation after a change at YubiCo; invalid issuer/OTP digits in TOTP org settings; API clients posting raw config that never passed client-side validation.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — 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/b57c003b4ee4e313. Report an issue: GitHub.

Appendix: source

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

                        (new MfaOrgSettingsDuoService($data))->validateDuoSettings($client, $skipHealthcheck === false);
                    } catch (CustomValidationException $exception) {
                        $errors = $exception->getErrors();
                    }
                    break;
                case MfaSettings::PROVIDER_TOTP:
                    // Nothing else to validate
                    break;
                default:
                    $errors[$provider]['invalidProvider'] = __('Unknown MFA provider: {0}.', $provider);
                    break;
            }
            if (isset($errors[$provider])) {
                $results[$provider] = $errors[$provider];
            }
        }
        if (count($results) !== 0) {
            $msg = __('Could not validate multi-factor authentication provider configuration.');
            throw new CustomValidationException($msg, $results);
        }

        return true;
    }

    /**
     * Save a user provided org settings in database
     *
     * @throws \App\Error\Exception\CustomValidationException in case of validation error
     * @throws \Cake\Http\Exception\InternalErrorException
     * @param array $data user provided input
     * @param \App\Utility\UserAccessControl $uac user access control
     * @param \Duo\DuoUniversal\Client|null $client Duo SDK Client
     * @param array $options Options used to save & validate organisation settings
     * @return void
     */
    public function save(array $data, UserAccessControl $uac, ?Client $client = null, array $options = []): void
    {

View on GitHub (pinned to 31c1bbc10f)