{"record":{"id":"fe3afe0c219739c1","repo":"passbolt/passbolt_api","slug":"could-not-validate-settings","errorCode":null,"errorMessage":"Could not validate settings.","messagePattern":"Could not validate settings\\.","errorType":"validation","errorClass":"CustomValidationException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/DirectorySync/src/Controller/DirectorySettingsController.php","lineNumber":82,"sourceCode":"        $this->success(__('The operation was successful.'), $formData);\n    }\n\n    /**\n     * Update the settings\n     *\n     * @return void\n     */\n    public function update()\n    {\n        if (!$this->User->isAdmin()) {\n            throw new ForbiddenException(__('You are not authorized to access that location.'));\n        }\n\n        $data = $this->request->getData();\n        $form = new LdapConfigurationForm();\n        if (!$form->validate($data)) {\n            $errors = $form->getErrors();\n            throw new CustomValidationException(__('Could not validate settings.'), $errors);\n        }\n        try {\n            $form->execute($data);\n        } catch (Exception $e) {\n            throw new BadRequestException(\n                __('Could not save the settings. {0}', $e->getMessage()),\n                null,\n                $e\n            );\n        }\n\n        $uac = $this->User->getAccessControl();\n        $settings = LdapConfigurationForm::formatFormDataToOrgSettings($data);\n        $directoryOrgSettings = new DirectoryOrgSettings($settings);\n        $directoryOrgSettings->save($uac);\n\n        $this->success(__('The operation was successful.'));\n    }","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/DirectorySync/src/Controller/DirectorySettingsController.php#L64-L100","documentation":"Thrown when LdapConfigurationForm::validate() fails on the POST /directorysync/settings payload, wrapping the form's field errors in a CustomValidationException (HTTP 400 with error details). The data did not satisfy the LDAP configuration form's validation rules (required fields, host format, port, credentials structure, etc.).","triggerScenarios":"POST /directorysync/settings with a payload missing required fields (e.g. directory_type, hosts, port) or with invalid values (non-numeric port, unknown directory_type), so $form->validate($data) returns false.","commonSituations":"Frontend sending stale/renamed field names after a passbolt upgrade; hand-crafted API scripts omitting nested LDAP fields; extra/misspelled keys; port as string vs int; missing enabled or sync-contents flags.","solutions":["Read the `errors` body of the 400 response to see exactly which fields failed and fix them.","Compare your payload against the current LdapConfigurationForm validation rules for your passbolt version (field names changed across versions).","Validate locally before sending: required fields present, port numeric, directory_type in the allowed list.","Test the same payload through the admin UI to confirm the expected shape.","Use the /directorysync/test endpoint first to iterate on the payload without saving."],"exampleFix":"// before\n{\"hosts\": \"ldap.example.com\", \"port\": \"abc\"}\n// 400 Could not validate settings. port._numeric\n// after\n{\"directory_type\": \"ldap\", \"hosts\": \"ldap.example.com\", \"port\": 389, \"enabled\": true}","handlingStrategy":"validation","validationCode":"function validateLdapSettingsPayload(d) {\n  const errors = [];\n  if (!d.directory_type) errors.push('directory_type is required');\n  if (!d.hosts) errors.push('hosts is required');\n  if (!Number.isInteger(d.port) || d.port <= 0) errors.push('port must be a positive integer');\n  if (errors.length) throw new Error('Invalid settings: ' + errors.join('; '));\n  return true;\n}\nvalidateLdapSettingsPayload(payload);","typeGuard":"function isValidLdapPayload(d) {\n  return typeof d === 'object' && d !== null\n    && typeof d.directory_type === 'string'\n    && typeof d.hosts === 'string'\n    && Number.isInteger(d.port);\n}","tryCatchPattern":"try {\n    await api.post('/directorysync/settings.json', payload);\n} catch (e) {\n    if (e.response?.status === 400 && e.response.data?.errors) {\n        console.error('Field errors:', e.response.data.errors);\n        // map errors back to form fields and correct the payload\n    }\n    throw e;\n}","preventionTips":["Mirror the LdapConfigurationForm rules in your client-side form validation.","Pin payload shape to the passbolt version you run; field names change between versions.","Use the /directorysync/test endpoint to sanity-check payloads before saving.","Always send port as a number and use documented field names."],"tags":["validation","http-400","ldap-configuration","form-validation"],"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"}