passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException

The SCIM setting identifier should be a valid UUID.

Error message

The SCIM setting identifier should be a valid UUID.

What it means

ScimSetSettingsService::saveSettings() validates the optional $id path parameter with Cake's Validation::uuid() before using it. When updating settings, the URL is expected to be /scim-settings/<uuid>; a non-UUID id means the client is calling PUT with a malformed identifier, so a 400 BadRequestException is thrown.

Solutions

  1. Pass a valid RFC 4122 UUID in the URL; fetch the current settings id first with GET /scim-settings and use its `id` field.
  2. If the intent was to CREATE settings, call POST /scim-settings without an id rather than PUT with a bogus id.
  3. Fix the client-side URL template so it interpolates the real id, e.g. `/scim-settings/${settings.id}`.

Example fix

// before
fetch('/scim-settings/1', {method:'PUT', ...});
// after
const settings = await (await fetch('/scim-settings.json')).json();
fetch(`/scim-settings/${settings.id}`, {method:'PUT', ...});
Defensive patterns

Strategy: validation

Validate before calling

if (id && !/^\d{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id)) {
  throw new Error('SCIM settings id must be a UUID, got: ' + id);
}

Type guard

const isUuid = (v) => typeof v === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v);

Try / catch

try {
  await api.put(`/scim-settings/${id}.json`, payload);
} catch (e) {
  if (e.response?.status === 400) { /* re-fetch settings id and retry as create/update */ }
}

Prevention

When it happens

Trigger: PUT /scim-settings/<id> where <id> is not a valid UUID (empty string is falsy and skips the check, but any other malformed value like a slug, numeric id, or truncated uuid triggers it).

Common situations: API client constructing the update URL from a wrong field, hardcoding an id placeholder, or sending a name/slug instead of the settings row UUID; also script errors concatenating the base URL with a partial id.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/c79645df32992398. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/Scim/src/Service/ScimSetSettingsService.php:63

    public const SCIM_SETTINGS_UPDATE_EVENT_NAME = 'scim_settings_update_event_name';

    /**
     * @param \App\Utility\UserAccessControl $uac
     * @param array $data
     * @param string|null $id
     * @return array
     * @throws \Exception
     */
    public function saveSettings(UserAccessControl $uac, array $data, ?string $id = null): array
    {
        // Capture the raw plaintext token before form hashes it with bcrypt
        $rawSecretToken = $data['secret_token'] ?? null;

        $form = new ScimSettingsForm();
        if ($id) {
            if (!Validation::uuid($id)) {
                throw new BadRequestException(__('The SCIM setting identifier should be a valid UUID.'));
            }
            $data['id'] = $id;
        }

        // 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) {

View on GitHub (pinned to 31c1bbc10f)