{"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/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/user-admin.service.ts#L53-L89","documentation":"Thrown (as BadRequestException) by UserAdminService.update when dto.email is provided and userRepository.getByEmail returns a different user (id mismatch). Email must be unique across the instance, so a collision is rejected before the update is applied.","triggerScenarios":"PUT /admin/users/:id with an email already claimed by another account.","commonSituations":"Merging duplicate accounts; user changed email to one already in the directory; case/whitespace differences that resolve to the same stored address.","solutions":["Pick a unique email not already associated with an account.","If the email legitimately belongs to this user, delete or rename the conflicting account first.","Normalize the email (trim/lowercase) before submit to avoid accidental collisions."],"exampleFix":"// before\nawait usersApi.update(id, { email: 'taken@example.com' });\n// after\nconst free = await pickUniqueEmail();\nawait usersApi.update(id, { email: free });","handlingStrategy":"validation","validationCode":"const owner = await userRepository.getByEmail(dto.email.trim().toLowerCase());\nif (owner && owner.id !== id) { /* show 'email taken' error, do not PUT */ }","typeGuard":null,"tryCatchPattern":"try { await usersApi.update(id, dto); }\ncatch (e) {\n  if (e instanceof BadRequestException && e.message === 'Email is not available') {\n    // prompt for a different email\n  }\n}","preventionTips":["Normalize (trim, lowercase) emails client-side before submit.","Debounce-check email availability as the user types.","Before account merges, rename the duplicate account's email first."],"tags":["users","validation","duplicate","email","bad-request"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}