passbolt/passbolt_api · error · Passbolt\Scim\Exception\ResourceNotFoundException
The resource with id ` ` is already deleted
Error message
The %s resource with id `%s` is already deleted
What it means
The user lookup intentionally includes soft-deleted users (findDeleted: true). If the matched user entity has deleted = true, setFromDatabase() throws ResourceNotFoundException with 'is already deleted' so that PATCH/PUT on a soft-deleted user fails clearly instead of silently resurrecting or modifying an inactive account.
Solutions
- Remove/deprovision the user on the IdP side so it stops syncing a deleted account.
- If the user should be active again, restore them in passbolt (undelete via users table/admin tooling) before applying SCIM operations.
- Recreate the user via POST /scim/v2/Users if a fresh account is desired.
- Catch ResourceNotFoundException on the client and treat it as a deprovision signal rather than retrying.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check soft-delete state
$user = $usersTable->find()->where(['id' => $uuid])->first();
if ($user && $user->deleted) {
throw new RuntimeException("User $uuid is soft-deleted; skipping SCIM operation");
} Try / catch
try {
$resource->setFromDatabase($uuid);
} catch (ResourceNotFoundException $e) {
if (str_contains($e->getMessage(), 'is already deleted')) {
// IdP should deprovision the user instead of patching
}
} Prevention
- Treat passbolt deletions as authoritative: deprovision on the IdP too.
- Distinguish the 'not found' vs 'already deleted' messages to pick skip vs recreate flows.
- Restore soft-deleted users before applying attribute updates.
- Monitor IdP sync logs for repeated patch attempts on deleted users.
When it happens
Trigger: PATCH or PUT /scim/v2/Users/{uuid} where the UUID exists but the user row has deleted = true (user was deleted via passbolt UI/CLI and is in soft-delete state).
Common situations: IdP still has the user assigned to the passbolt app and keeps trying to sync attributes after an admin deleted the user; race between deprovisioning and attribute sync; restore-workflow tests hitting deleted fixtures.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- The resource with id ` ` was not found
- Invalid schema for SCIM User Resource
- The ResourceType ` ` is invalid or not supported
- The Schema ` ` is invalid or not supported
- The SCIM plugin is disabled.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/77280f612f154914.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Scim/src/Utility/Resource/UserScimResource.php:238
*/
public function setFromDatabase(string $internalId): self
{
if (!Validation::uuid($internalId)) {
throw new BadRequestException(__('The user identifier should be a valid UUID.'));
}
/** @var \App\Model\Entity\User|null $userEntity */
$userEntity = $this->Users
->findForScim([$this->Users->aliasField('id') => $internalId], findDeleted: true)
->contain(['Profiles', 'ScimEntries'])
->first();
$this->userEntity = $userEntity;
if (!$this->userEntity) {
throw new ResourceNotFoundException(
sprintf('The %s resource with id `%s` was not found', $this->getType(), $internalId)
);
}
if ($this->userEntity->deleted) {
throw new ResourceNotFoundException(
sprintf('The %s resource with id `%s` is already deleted', $this->getType(), $internalId)
);
}
$this->id = $this->userEntity->id;
$this->externalId = $this->userEntity->scim_entry?->external_identifier;
$this->userName = $this->userEntity->scim_entry?->scim_name;
$this->email = $this->userEntity->username;
$this->firstName = $this->userEntity->profile?->first_name;
$this->lastName = $this->userEntity->profile?->last_name;
$this->active = !$this->userEntity->disabled;
return $this;
}
/**
* @inheritDoc
*/View on GitHub (pinned to 31c1bbc10f)