{"record":{"id":"a64d9f36ea2843c7","repo":"immich-app/immich","slug":"email-is-not-available-a64d9f","errorCode":null,"errorMessage":"Email is not available","messagePattern":"Email is not available","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/user-admin.service.ts","lineNumber":71,"sourceCode":"    return mapUserAdmin(user);\n  }\n\n  async update(auth: AuthDto, id: string, dto: UserAdminUpdateDto): Promise<UserAdminResponseDto> {\n    const user = await this.findOrFail(id, {});\n\n    if (dto.isAdmin !== undefined && dto.isAdmin !== auth.user.isAdmin && auth.user.id === id) {\n      throw new BadRequestException('Admin status can only be changed by another admin');\n    }\n\n    if (dto.quotaSizeInBytes && user.quotaSizeInBytes !== dto.quotaSizeInBytes) {\n      await this.userRepository.syncUsage(id);\n    }\n\n    if (dto.email) {\n      const duplicate = await this.userRepository.getByEmail(dto.email);\n      if (duplicate && duplicate.id !== id) {\n        this.logger.debug('Email already in use by another account');\n        throw new BadRequestException('Email is not available');\n      }\n    }\n\n    if (dto.storageLabel) {\n      const duplicate = await this.userRepository.getByStorageLabel(dto.storageLabel);\n      if (duplicate && duplicate.id !== id) {\n        throw new BadRequestException('Storage label already in use by another account');\n      }\n    }\n\n    if (dto.password) {\n      dto.password = await this.cryptoRepository.hashBcrypt(dto.password, SALT_ROUNDS);\n    }\n\n    if (dto.pinCode) {\n      dto.pinCode = await this.cryptoRepository.hashBcrypt(dto.pinCode, SALT_ROUNDS);\n    }\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/user-admin.service.ts#L53-L89","documentation":"Thrown by UserAdminService.update when the requested new email is already used by a different account. Uniqueness of emails is enforced per instance; the check excludes the target user itself (duplicate.id !== id). It is a 400 BadRequest for a uniqueness conflict.","triggerScenarios":"PUT/PATCH /api/admin/users/:id with dto.email equal to the email of another existing user. Also triggered by case/format variants that resolve to an existing account, or re-inviting a user whose email was taken by a deleted-but-restored account.","commonSituations":"Merging accounts or changing a user's email to one already registered; renaming a user to a former employee's address that still exists; duplicate registrations before the update attempt.","solutions":["Choose a different email or free up the address by updating/removing the conflicting account first","Check availability with a user lookup by email before submitting the update","If the duplicate account is stale, delete it, then retry the email change"],"exampleFix":"// before\nawait adminApi.updateUser(userId, { email: 'shared@corp.com' });\n// after\nconst existing = await adminApi.getUserByEmail('shared@corp.com');\nif (existing && existing.id !== userId) throw new Error('email taken');\nawait adminApi.updateUser(userId, { email: 'shared@corp.com' });","handlingStrategy":"validation","validationCode":"const existing = await adminApi.getUserByEmail(dto.email);\nif (existing && existing.id !== id) {\n  throw new Error(`email ${dto.email} is already in use`);\n}","typeGuard":null,"tryCatchPattern":"try { await adminApi.updateUser(id, dto); } catch (e) {\n  if (e.response?.status === 400 && /Email is not available/.test(e.response?.data?.message ?? '')) {\n    // prompt for a different email or resolve the conflicting account\n  }\n  throw e;\n}","preventionTips":["Check email availability before submitting updates","Maintain unique-email enforcement at the input layer","Resolve or remove conflicting accounts during migrations"],"tags":["duplicate","uniqueness","email"],"backgroundTag":"record-already-exists","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"}