passbolt/passbolt_api · error · Passbolt\Scim\Exception\FormValidationException
Could not validate the SCIM settings found in database.
Error message
Could not validate the SCIM settings found in database.
What it means
ScimGetSettingsService::getSettings() reads the single SCIM settings row from the database, decrypts it, and re-validates it with ScimSettingsForm. If the stored data fails form validation, it wraps the failure in an InternalErrorException with this message. This signals corrupted, legacy-format, or manually-tampered SCIM settings persisted in the `scim_settings` table — not a client input problem.
Solutions
- Inspect the decrypted settings row: delete the row from scim_settings so the plugin falls back to default (unset) settings, then re-create the SCIM settings via the admin UI.
- Check the form errors (they are attached to the chained FormValidationException) via the exception stack/log to see exactly which field failed validation.
- Verify the server encryption keys are intact — a wrong key yields garbage on decryptSettings(), which then fails validation.
- If this appeared after a passbolt upgrade, compare ScimSettingsForm validation rules with the stored data and migrate the row to the expected format instead of deleting.
Example fix
// Remove corrupted row so defaults are used (MySQL) DELETE FROM scim_settings WHERE id = '<corrupted-row-uuid>'; // Then re-save SCIM settings through Admin > SCIM settings UI
Defensive patterns
Strategy: try-catch
Try / catch
try {
$settings = (new ScimGetSettingsService())->getSettings();
} catch (InternalErrorException $e) {
$previous = $e->getPrevious();
if ($previous instanceof FormValidationException) {
Log::error('SCIM settings corrupt: ' . json_encode($previous->getForm()->getErrors()));
}
// fall back to default/unset settings and prompt admin to re-save
} Prevention
- Never edit the scim_settings table manually; use the admin UI/API.
- After restoring DB backups, re-save SCIM settings through the API once.
- Verify server GPG/encryption keys before enabling SCIM.
- Log form errors from the chained FormValidationException to catch format drift early.
When it happens
Trigger: GET /scim-settings (admin settings read) when a row exists in scim_settings whose decrypted payload fails ScimSettingsForm validation: e.g. missing required keys, malformed setting_id/scim_user_id, or values written by an older plugin version whose schema no longer validates.
Common situations: Manual edits to the scim_settings table rows, restore of a database from an older passbolt version, partial/corrupted encrypted payload after key changes, or an upgrade that tightened ScimSettingsForm validation rules against previously-accepted data.
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
- " " is not a valid search filter.
- " " is not a valid search filter. It is not a UTF8 string.
- " " is not a valid search filter. It should be between 1…
- " " is not a valid user filter.
- " " is not a valid value for filter .
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/6cb7013c80893e44.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Scim/src/Service/ScimGetSettingsService.php:74
/** @var \Passbolt\Scim\Model\Table\ScimSettingsTable $scimSettingsTable */
$scimSettingsTable = $this->fetchTable('Passbolt/Scim.ScimSettings');
/** @var \Passbolt\Scim\Model\Entity\ScimSetting|null $settings */
$settings = $scimSettingsTable->find()->first();
if (is_null($settings)) {
return null;
}
$value = $this->decryptSettings($settings);
$form = new ScimSettingsForm();
if (!$form->execute($value, ['newRecord' => false])) {
$validationException = new FormValidationException(
__('Could not validate the SCIM settings found in database.'),
$form
);
throw new InternalErrorException($validationException->getMessage(), 500, $validationException);
}
return ScimSettingsDto::createFromArray([
'id' => $settings->id,
'setting_id' => Hash::get($value, 'setting_id'),
'scim_user_id' => Hash::get($value, 'scim_user_id'),
'base_api_endpoint' => Router::url('scim/v2/' . Hash::get($value, 'setting_id'), true),
'expired' => Hash::get($value, 'expired'),
'created' => $settings->created,
'created_by' => $settings->created_by,
'modified' => $settings->modified,
'modified_by' => $settings->modified_by,
]);
}
}
View on GitHub (pinned to 31c1bbc10f)