{"record":{"id":"0b106722f539a55a","repo":"immich-app/immich","slug":"cannot-delete-your-own-account","errorCode":null,"errorMessage":"Cannot delete your own account","messagePattern":"Cannot delete your own account","errorType":"exception","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"server/src/services/user-admin.service.ts","lineNumber":103,"sourceCode":"\n    if (dto.pinCode) {\n      dto.pinCode = await this.cryptoRepository.hashBcrypt(dto.pinCode, SALT_ROUNDS);\n    }\n\n    if (dto.storageLabel === '') {\n      dto.storageLabel = null;\n    }\n\n    const updatedUser = await this.userRepository.update(id, { ...dto, updatedAt: new Date() });\n\n    return mapUserAdmin(updatedUser);\n  }\n\n  async delete(auth: AuthDto, id: string, dto: UserAdminDeleteDto): Promise<UserAdminResponseDto> {\n    const { force } = dto;\n    await this.findOrFail(id, {});\n    if (auth.user.id === id) {\n      throw new ForbiddenException('Cannot delete your own account');\n    }\n\n    await this.albumRepository.softDeleteAll(id);\n\n    const status = force ? UserStatus.Removing : UserStatus.Deleted;\n    const user = await this.userRepository.update(id, { status, deletedAt: new Date() });\n\n    await this.eventRepository.emit('UserTrash', user);\n\n    if (force) {\n      await this.jobRepository.queue({ name: JobName.UserDelete, data: { id: user.id, force } });\n    }\n\n    return mapUserAdmin(user);\n  }\n\n  async restore(auth: AuthDto, id: string): Promise<UserAdminResponseDto> {\n    await this.findOrFail(id, { withDeleted: true });","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/user-admin.service.ts#L85-L121","documentation":"Thrown by UserAdminService.delete when an admin attempts to delete their own account. Self-deletion is forbidden (403 ForbiddenException) to avoid orphaning the instance's last admin and breaking session state. Deletion must be performed by a different admin.","triggerScenarios":"DELETE /api/admin/users/:id where id === auth.user.id, regardless of the force flag. findOrFail succeeds, then the identity comparison throws.","commonSituations":"Cleaning up user lists with a script that includes the caller's own ID; an admin testing the delete endpoint on themselves; single-admin instances where the only admin tries to remove their account.","solutions":["Have another admin perform the deletion","Promote a second user to admin, then delete the original account with that account","Skip the caller's own ID in bulk-delete scripts (filter out auth.user.id)"],"exampleFix":"// before\nfor (const id of userIds) await adminApi.deleteUser(id, { force: false });\n// after\nfor (const id of userIds.filter(u => u !== myUserId)) await adminApi.deleteUser(id, { force: false });","handlingStrategy":"validation","validationCode":"if (id === auth.user.id) {\n  throw new Error('cannot delete your own account; use another admin');\n}","typeGuard":null,"tryCatchPattern":"try { await adminApi.deleteUser(id, dto); } catch (e) {\n  if (e.response?.status === 403 && /your own account/.test(e.response?.data?.message ?? '')) {\n    // skip this id in bulk flows; require another admin session\n  }\n  throw e;\n}","preventionTips":["Exclude the current user's ID from bulk-delete lists","Keep at least two admins so self-deletion is never needed","Disable delete actions for the logged-in row in admin UIs"],"tags":["permission","self-modification","deletion"],"backgroundTag":"permission-denied","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}