passbolt/passbolt_api · error · FormValidationException

Could not validate the smtp settings found in database.

Error message

Could not validate the smtp settings found in database.

What it means

Thrown by SmtpSettingsGetSettingsInDbService::getSettings when the SMTP settings stored in the database fail validation against EmailConfigurationForm. Before throwing, the form gets `source: 'database'` appended so diagnostics show which source was invalid; a FormValidationException is raised.

Solutions

  1. Read the validation errors attached to the FormValidationException; the `source` field will confirm the problem came from the DB record.
  2. Re-save correct SMTP settings via POST /smtp-settings.json so a valid record replaces the bad one.
  3. Fix or delete the offending DB row and fall back to file/env configuration temporarily.
  4. After a passbolt upgrade, re-test SMTP settings since validation rules may have tightened.

Example fix

// before (bad DB record)
{ "sender_email": "not-an-email", "port": "smtp" }

// after: re-save valid settings
POST /smtp-settings.json { "sender_email": "no-reply@mycompany.com", "port": 587, "host": "smtp.mycompany.com", ... }
Defensive patterns

Strategy: validation

Validate before calling

$form = new EmailConfigurationForm();
$stored = /* fetch DB row */;
if (!$form->check($stored)) {
    // repair or delete the DB row before invoking the get service
}

Try / catch

try {
    $data = $inDbService->getSettings();
} catch (FormValidationException $e) {
    $form = $e->getForm();
    Log::error('DB smtp settings invalid, source=' . $form->getData()['source'] ?? 'database');
    // fall back to file/env settings
}

Prevention

When it happens

Trigger: Reading DB-stored SMTP settings (used by the smtp-settings get/test endpoints) where the stored record has invalid values: malformed sender email, out-of-range port, null/empty required fields such as host, or rows written by older versions with different schemas.

Common situations: Settings saved by an older passbolt version that current validation rejects; partial writes; manual DB edits to the smtp_settings/organization_settings record; corrupted records after failed saves.

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/3324d8bf05d78343. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/SmtpSettings/src/Service/SmtpSettingsGetSettingsInDbService.php:54

     * @return array|null
     * @throws \App\Error\Exception\FormValidationException if the data does not validate the EmailConfigurationForm
     * @throws \Cake\Http\Exception\InternalErrorException if the data in the DB cannot be decrypted
     * @throws \Cake\Database\Exception\MissingConnectionException if the database is not in place (this is the case during installation)
     */
    public function getSettings(): ?array
    {
        $form = new EmailConfigurationForm();
        $data = $this->readConfigInDB();

        if (is_null($data)) {
            return null;
        }

        if (!$form->execute($data)) {
            // An exception is thrown, the settings should not be consumed, but the source is appended for
            // diagnostic purposes.
            $form->set('source', SmtpSettingsGetService::SMTP_SETTINGS_SOURCE_DB);
            throw new FormValidationException(__('Could not validate the smtp settings found in database.'), $form);
        }

        return $form->getData();
    }

    /**
     * Reads SMTP in the organization settings table
     *
     * @return array|null
     * @throws \Cake\Http\Exception\InternalErrorException if the data in the DB cannot be decrypted
     */
    protected function readConfigInDB(): ?array
    {
        /** @var \App\Model\Table\OrganizationSettingsTable $OrganizationSettings */
        $OrganizationSettings = TableRegistry::getTableLocator()->get('OrganizationSettings');
        try {
            $settings = $OrganizationSettings->getByProperty(self::SMTP_SETTINGS_PROPERTY_NAME);
        } catch (Throwable $e) {

View on GitHub (pinned to 31c1bbc10f)