immich-app/immich · error · ForbiddenException
Cannot delete your own account
Error message
Cannot delete your own account
What it means
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.
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)
Example fix
// before
for (const id of userIds) await adminApi.deleteUser(id, { force: false });
// after
for (const id of userIds.filter(u => u !== myUserId)) await adminApi.deleteUser(id, { force: false }); Defensive patterns
Strategy: validation
Validate before calling
if (id === auth.user.id) {
throw new Error('cannot delete your own account; use another admin');
} Try / catch
try { await adminApi.deleteUser(id, dto); } catch (e) {
if (e.response?.status === 403 && /your own account/.test(e.response?.data?.message ?? '')) {
// skip this id in bulk flows; require another admin session
}
throw e;
} Prevention
- 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
When it happens
Trigger: DELETE /api/admin/users/:id where id === auth.user.id, regardless of the force flag. findOrFail succeeds, then the identity comparison throws.
Common situations: 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.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/0b106722f539a55a.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/user-admin.service.ts:103
if (dto.pinCode) {
dto.pinCode = await this.cryptoRepository.hashBcrypt(dto.pinCode, SALT_ROUNDS);
}
if (dto.storageLabel === '') {
dto.storageLabel = null;
}
const updatedUser = await this.userRepository.update(id, { ...dto, updatedAt: new Date() });
return mapUserAdmin(updatedUser);
}
async delete(auth: AuthDto, id: string, dto: UserAdminDeleteDto): Promise<UserAdminResponseDto> {
const { force } = dto;
await this.findOrFail(id, {});
if (auth.user.id === id) {
throw new ForbiddenException('Cannot delete your own account');
}
await this.albumRepository.softDeleteAll(id);
const status = force ? UserStatus.Removing : UserStatus.Deleted;
const user = await this.userRepository.update(id, { status, deletedAt: new Date() });
await this.eventRepository.emit('UserTrash', user);
if (force) {
await this.jobRepository.queue({ name: JobName.UserDelete, data: { id: user.id, force } });
}
return mapUserAdmin(user);
}
async restore(auth: AuthDto, id: string): Promise<UserAdminResponseDto> {
await this.findOrFail(id, { withDeleted: true });View on GitHub (pinned to e55ac299a4)