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

  1. Read the `errors` body of the 400 response to see exactly which fields failed and fix them.
  2. Compare your payload against the current LdapConfigurationForm validation rules for your passbolt version (field names changed across versions).
  3. Validate locally before sending: required fields present, port numeric, directory_type in the allowed list.
  4. Test the same payload through the admin UI to confirm the expected shape.
  5. 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

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


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)