passbolt/passbolt_api · error · CustomValidationException
Could not validate settings.
Error message
Could not validate settings.
What it means
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.).
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.
Example fix
// before
{"hosts": "ldap.example.com", "port": "abc"}
// 400 Could not validate settings. port._numeric
// after
{"directory_type": "ldap", "hosts": "ldap.example.com", "port": 389, "enabled": true} Defensive patterns
Strategy: validation
Validate before calling
function validateLdapSettingsPayload(d) {
const errors = [];
if (!d.directory_type) errors.push('directory_type is required');
if (!d.hosts) errors.push('hosts is required');
if (!Number.isInteger(d.port) || d.port <= 0) errors.push('port must be a positive integer');
if (errors.length) throw new Error('Invalid settings: ' + errors.join('; '));
return true;
}
validateLdapSettingsPayload(payload); Type guard
function isValidLdapPayload(d) {
return typeof d === 'object' && d !== null
&& typeof d.directory_type === 'string'
&& typeof d.hosts === 'string'
&& Number.isInteger(d.port);
} Try / catch
try {
await api.post('/directorysync/settings.json', payload);
} catch (e) {
if (e.response?.status === 400 && e.response.data?.errors) {
console.error('Field errors:', e.response.data.errors);
// map errors back to form fields and correct the payload
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
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
- Could not delete favorite.
- Could not save the account recovery setting.
- Could not validate comment data.
- Could not validate the metadata key data.
- Could not validate the metadata key data.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/fe3afe0c219739c1.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/DirectorySync/src/Controller/DirectorySettingsController.php:82
$this->success(__('The operation was successful.'), $formData);
}
/**
* Update the settings
*
* @return void
*/
public function update()
{
if (!$this->User->isAdmin()) {
throw new ForbiddenException(__('You are not authorized to access that location.'));
}
$data = $this->request->getData();
$form = new LdapConfigurationForm();
if (!$form->validate($data)) {
$errors = $form->getErrors();
throw new CustomValidationException(__('Could not validate settings.'), $errors);
}
try {
$form->execute($data);
} catch (Exception $e) {
throw new BadRequestException(
__('Could not save the settings. {0}', $e->getMessage()),
null,
$e
);
}
$uac = $this->User->getAccessControl();
$settings = LdapConfigurationForm::formatFormDataToOrgSettings($data);
$directoryOrgSettings = new DirectoryOrgSettings($settings);
$directoryOrgSettings->save($uac);
$this->success(__('The operation was successful.'));
}View on GitHub (pinned to 31c1bbc10f)