passbolt/passbolt_api · warning · Cake\Http\Exception\BadRequestException
Please delete previous settings before creating again.
Error message
Please delete previous settings before creating again.
What it means
The SCIM plugin stores at most one settings row. saveSettings() enforces this: if no $id was supplied (i.e., a create operation) but a settings row already exists, it throws BadRequestException telling the caller to delete the previous settings first. This prevents duplicate/conflicting SCIM configurations.
Solutions
- Check GET /scim-settings before creating; if settings exist, issue PUT /scim-settings/<existing-id> instead of POST.
- Delete the existing settings (DELETE /scim-settings/<id>) if replacement is truly intended, then create anew.
- Make provisioning scripts idempotent: fetch-then-update rather than always POST.
Example fix
// before
await api.post('/scim-settings.json', payload);
// after
const existing = await api.get('/scim-settings.json');
if (existing.data) {
await api.put(`/scim-settings/${existing.data.id}.json`, payload);
} else {
await api.post('/scim-settings.json', payload);
} Defensive patterns
Strategy: validation
Validate before calling
const { data } = await api.get('/scim-settings.json');
if (data) {
return api.put(`/scim-settings/${data.id}.json`, payload); // update, don't create
}
return api.post('/scim-settings.json', payload); Try / catch
try {
await api.post('/scim-settings.json', payload);
} catch (e) {
if (e.response?.status === 400 && /delete previous/i.test(e.response.data?.message ?? '')) {
const { data: cur } = await api.get('/scim-settings.json');
await api.put(`/scim-settings/${cur.id}.json`, payload);
}
} Prevention
- Make provisioning scripts idempotent: GET first, then update or create.
- Refresh the admin UI after save so the form switches to update mode.
- Remember the plugin is singleton-per-installation: one settings row only.
When it happens
Trigger: POST /scim-settings when scim_settings already contains a row — typically a second admin clicking 'save' on a create form, or an automation trying to re-provision settings that already exist.
Common situations: Setup scripts run twice without idempotency checks; UI state out of sync (form still in 'create' mode after settings were saved); multi-admin environments where another admin configured SCIM first.
Related errors
- The resource type ` ` is not valid
- The SCIM plugin is disabled.
- Could not validate the SCIM settings.
- Could not validate the SCIM settings found in database.
- The filter for attribute
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/741fe12db099526b.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Scim/src/Service/ScimSetSettingsService.php:85
// Using this approach to avoid checking for setting_id duplicates on update
$validate = $id ? 'update' : 'extended';
if (!$form->execute($data, ['validate' => $validate])) {
throw new FormValidationException(
__('Could not validate the SCIM settings.'),
$form
);
}
/** @var \Passbolt\Scim\Model\Table\ScimSettingsTable $scimSettingsTable */
$scimSettingsTable = $this->fetchTable('Passbolt/Scim.ScimSettings');
/** @var \Passbolt\Scim\Model\Entity\ScimSetting|null $current */
$current = $scimSettingsTable->find()->first();
if (!$current && $id) {
throw new NotFoundException(__('The SCIM plugin is disabled.'));
}
if (!$id && $current) {
throw new BadRequestException(__('Please delete previous settings before creating again.'));
}
if ($current && $current->id !== $id) {
throw new NotFoundException(__('The uuid in the url doesn\'t match any known setting record.'));
}
$currentValue = [];
$isDummyToken = $rawSecretToken === self::SCIM_SECRET_TOKEN_DUMMY;
if ($current) {
$currentValue = $this->decryptSettings($current);
$form->set('setting_id', Hash::get($currentValue, 'setting_id'));
if (!$form->getData('secret_token') || $isDummyToken) {
$form->set('secret_token', Hash::get($currentValue, 'secret_token'));
}
}
$settingsData = $form->getData();
$isTokenRotated = $this->isTokenRotated($rawSecretToken, $currentValue);
if (!$current || $isTokenRotated) {View on GitHub (pinned to 31c1bbc10f)