{"record":{"id":"27c3df8ef88f25e1","repo":"passbolt/passbolt_api","slug":"could-not-validate-the-password-expiry-settings","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/PasswordExpiryGetSettingsService.php","lineNumber":67,"sourceCode":"        $passwordExpirySettingsTable = $this->fetchTable('Passbolt/PasswordExpiry.PasswordExpirySettings');\n\n        /** @var \\Passbolt\\PasswordExpiry\\Model\\Entity\\PasswordExpirySetting|null $passwordExpirySettings */\n        $passwordExpirySettings = $passwordExpirySettingsTable->find()->first();\n\n        if (is_null($passwordExpirySettings)) {\n            $this->dto = $this->createDTOFromArray([]);\n\n            return $this->dto;\n        }\n\n        if (!is_array($passwordExpirySettings->value)) {\n            throw new InternalErrorException('The value should be an array');\n        }\n\n        $data = $passwordExpirySettings->value;\n        $form = $this->getForm();\n        if (!$form->execute($data)) {\n            throw new FormValidationException(\n                __('Could not validate the password expiry settings.'),\n                $form\n            );\n        }\n        $this->dto = $this->createDTOFromEntity($passwordExpirySettings, $form);\n\n        return $this->dto;\n    }\n}\n","sourceCodeStart":49,"sourceCodeEnd":77,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/PasswordExpiry/src/Service/Settings/PasswordExpiryGetSettingsService.php#L49-L77","documentation":"FormValidationException thrown by PasswordExpiryGetSettingsService::get when stored settings value data fails the password expiry settings form validation. The persisted organization settings payload no longer satisfies the form rules, so building the DTO is aborted.","triggerScenarios":"Reading password expiry settings whose stored 'value' array (decoded from organization_settings) fails $form->execute($data) — e.g. invalid automatic_expiry_period format or wrong types.","commonSituations":"Settings written by an older plugin version or manually edited in the database using keys/period formats the current validation form rejects (e.g. '90' instead of '90d').","solutions":["Log or inspect $form->getErrors() to identify the failing field.","Re-save the password expiry settings through the API so they are validated and normalized.","Fix the stored value directly: use the documented period format like '90d' (N followed by d/w/m/y).","Check for plugin version drift and run migrations/update the plugin to align validation rules."],"exampleFix":"// before (stored value)\n{\"automatic_expiry\": {\"automatic_expiry_period\": \"90\"}}\n// after\n{\"automatic_expiry\": {\"automatic_expiry_period\": \"90d\"}}","handlingStrategy":"try-catch","validationCode":"if (isset($stored['automatic_expiry']['automatic_expiry_period']) && !preg_match('/^\\d+[dwmy]$/', $stored['automatic_expiry']['automatic_expiry_period'])) { // resave settings }","typeGuard":null,"tryCatchPattern":"try { $dto = $service->get(); } catch (FormValidationException $e) { $errs = $e->getForm()->getErrors(); }","preventionTips":["Never hand-edit stored settings rows; always save through the validated API form.","Keep the plugin version in sync so stored payloads match current validation rules.","Use the documented period format (e.g. '90d')."],"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"}