{"record":{"id":"44af9957d75e1a48","repo":"passbolt/passbolt_api","slug":"could-not-validate-the-password-expiry-settings-44af99","errorCode":null,"errorMessage":"Could not validate the password expiry settings.","messagePattern":"Could not validate the password expiry settings\\.","errorType":"validation","errorClass":"FormValidationException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/PasswordExpiry/src/Service/Settings/PasswordExpirySetSettingsService.php","lineNumber":43,"sourceCode":"class PasswordExpirySetSettingsService extends PasswordExpirySettingsAbstractService implements PasswordExpirySetSettingsServiceInterface // phpcs:ignore\n{\n    use EventDispatcherTrait;\n\n    /**\n     * Event name. Fired after password expiry settings has been saved.\n     *\n     * @var string\n     */\n    public const EVENT_SETTINGS_UPDATED = 'Service.PasswordExpirySetSettingsService.updated';\n\n    /**\n     * @inheritDoc\n     */\n    final public function createOrUpdate(ExtendedUserAccessControl $uac, array $data): PasswordExpirySettingsDto\n    {\n        $form = $this->getForm();\n        if (!$form->execute($data)) {\n            throw new FormValidationException(__('Could not validate the password expiry settings.'), $form);\n        }\n\n        /** @var \\Passbolt\\PasswordExpiry\\Model\\Table\\PasswordExpirySettingsTable $passwordExpirySettingsTable */\n        $passwordExpirySettingsTable = $this->fetchTable('Passbolt/PasswordExpiry.PasswordExpirySettings');\n\n        /** @var \\Passbolt\\PasswordExpiry\\Model\\Entity\\PasswordExpirySetting $passwordExpirySetting */\n        $passwordExpirySetting = $passwordExpirySettingsTable->createOrUpdateSetting(\n            $passwordExpirySettingsTable->getProperty(),\n            $this->createDTOFromArray($form->getData())->getValue(),\n            $uac\n        );\n\n        /** Dispatch settings updated event. */\n        $this->dispatchEvent(self::EVENT_SETTINGS_UPDATED, compact('uac'), $passwordExpirySetting);\n\n        return $this->createDTOFromEntity($passwordExpirySetting, $form);\n    }\n}","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/PasswordExpiry/src/Service/Settings/PasswordExpirySetSettingsService.php#L25-L61","documentation":"FormValidationException thrown by PasswordExpirySetSettingsService::createOrUpdate when the submitted settings payload fails the password expiry settings form validation ($form->execute returns false). Nothing is persisted when this fires.","triggerScenarios":"POST/PUT to /password-expiry/settings with a payload missing required keys, containing unknown keys, or with an invalid automatic_expiry_period / automatic_expiry_on_delete_on_expired value.","commonSituations":"Admin UI/API integrations sending period values like '3 months' or '90' instead of the required compact format ('90d'), or omitting the automatic_expiry object entirely.","solutions":["Inspect the FormValidationException errors (form->getErrors()) to identify failing fields.","Send the full expected payload with automatic_expiry containing valid boolean flags and a period in the accepted format (e.g. '90d').","Validate the payload client-side before posting.","Check the API docs/plugin version for the exact accepted schema."],"exampleFix":"// before\n{\"automatic_expiry\": {\"automatic_expiry_on_delete_on_expired\": \"yes\", \"automatic_expiry_period\": \"3 months\"}}\n// after\n{\"automatic_expiry\": {\"automatic_expiry_on_delete_on_expired\": true, \"automatic_expiry_period\": \"90d\"}}","handlingStrategy":"validation","validationCode":"$valid = preg_match('/^\\d+[dwmy]$/', $data['automatic_expiry']['automatic_expiry_period'] ?? '') && is_bool($data['automatic_expiry']['automatic_expiry_on_delete_on_expired'] ?? null);","typeGuard":null,"tryCatchPattern":"try { $dto = $service->createOrUpdate($uac, $data); } catch (FormValidationException $e) { $errs = $e->getForm()->getErrors(); }","preventionTips":["Build payloads from the documented DTO schema, not free-form arrays.","Send booleans as real booleans, not 'yes'/'no' strings.","Validate the period format client-side before posting."],"tags":["password-expiry","validation","form","settings"],"backgroundTag":"schema-validation-failed","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}