{"record":{"id":"77280f612f154914","repo":"passbolt/passbolt_api","slug":"the-s-resource-with-id-s-is-already-deleted","errorCode":null,"errorMessage":"The %s resource with id `%s` is already deleted","messagePattern":"The (.+?) resource with id `(.+?)` is already deleted","errorType":"exception","errorClass":"Passbolt\\Scim\\Exception\\ResourceNotFoundException","httpStatus":404,"severity":"error","filePath":"plugins/PassboltEe/Scim/src/Utility/Resource/UserScimResource.php","lineNumber":238,"sourceCode":"     */\n    public function setFromDatabase(string $internalId): self\n    {\n        if (!Validation::uuid($internalId)) {\n            throw new BadRequestException(__('The user identifier should be a valid UUID.'));\n        }\n        /** @var \\App\\Model\\Entity\\User|null $userEntity */\n        $userEntity = $this->Users\n            ->findForScim([$this->Users->aliasField('id') => $internalId], findDeleted: true)\n            ->contain(['Profiles', 'ScimEntries'])\n            ->first();\n        $this->userEntity = $userEntity;\n        if (!$this->userEntity) {\n            throw new ResourceNotFoundException(\n                sprintf('The %s resource with id `%s` was not found', $this->getType(), $internalId)\n            );\n        }\n        if ($this->userEntity->deleted) {\n            throw new ResourceNotFoundException(\n                sprintf('The %s resource with id `%s` is already deleted', $this->getType(), $internalId)\n            );\n        }\n\n        $this->id = $this->userEntity->id;\n        $this->externalId = $this->userEntity->scim_entry?->external_identifier;\n        $this->userName = $this->userEntity->scim_entry?->scim_name;\n        $this->email = $this->userEntity->username;\n        $this->firstName = $this->userEntity->profile?->first_name;\n        $this->lastName = $this->userEntity->profile?->last_name;\n        $this->active = !$this->userEntity->disabled;\n\n        return $this;\n    }\n\n    /**\n     * @inheritDoc\n     */","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Scim/src/Utility/Resource/UserScimResource.php#L220-L256","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check soft-delete state\n$user = $usersTable->find()->where(['id' => $uuid])->first();\nif ($user && $user->deleted) {\n    throw new RuntimeException(\"User $uuid is soft-deleted; skipping SCIM operation\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    $resource->setFromDatabase($uuid);\n} catch (ResourceNotFoundException $e) {\n    if (str_contains($e->getMessage(), 'is already deleted')) {\n        // IdP should deprovision the user instead of patching\n    }\n}","preventionTips":["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."],"tags":["scim","user","deleted","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}