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

  1. Check GET /scim-settings before creating; if settings exist, issue PUT /scim-settings/<existing-id> instead of POST.
  2. Delete the existing settings (DELETE /scim-settings/<id>) if replacement is truly intended, then create anew.
  3. 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

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


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)