{"record":{"id":"4f63f5cfebf0f691","repo":"immich-app/immich","slug":"email-is-not-available-4f63f5","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.service.ts","lineNumber":61,"sourceCode":"  async getMe(auth: AuthDto): Promise<UserAdminResponseDto> {\n    const user = await this.userRepository.get(auth.user.id, {});\n    if (!user) {\n      throw new BadRequestException('User not found');\n    }\n\n    return mapUserAdmin(user);\n  }\n\n  getCalendarHeatmap(auth: AuthDto, dto: CalendarHeatmapDto): Promise<CalendarHeatmapResponseDto> {\n    return getCalendarHeatmap(auth.user.id, dto, { asset: this.assetRepository });\n  }\n\n  async updateMe({ user }: AuthDto, dto: UserUpdateMeDto): Promise<UserAdminResponseDto> {\n    if (dto.email) {\n      const duplicate = await this.userRepository.getByEmail(dto.email);\n      if (duplicate && duplicate.id !== user.id) {\n        this.logger.warn('Email already in use by another account');\n        throw new BadRequestException('Email is not available');\n      }\n    }\n\n    const update: Updateable<UserTable> = {\n      email: dto.email,\n      name: dto.name,\n      avatarColor: dto.avatarColor,\n    };\n\n    if (dto.password) {\n      const hashedPassword = await this.cryptoRepository.hashBcrypt(dto.password, SALT_ROUNDS);\n      update.password = hashedPassword;\n      update.shouldChangePassword = false;\n    }\n\n    const updatedUser = await this.userRepository.update(user.id, update);\n\n    return mapUserAdmin(updatedUser);","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/user.service.ts#L43-L79","documentation":"updateMe rejects an email change when the requested email is already owned by a different user account. The service looks up the email in the user repository and compares the found duplicate's id with the authenticated user's id. If a different account holds the email, the change is refused with a 400 Bad Request.","triggerScenarios":"PUT /users/me with an email in the body whose value matches another existing user's email (duplicate.id !== user.id). Note that resubmitting your own current email is allowed since duplicate.id === user.id.","commonSituations":"Shared/family servers where two accounts try to use the same address; a user changing email to one that was later re-registered by an admin; seeding scripts importing users with colliding emails; stale client forms that pre-filled an old email now owned by someone else.","solutions":["Pick a different email address that is not registered on this Immich instance.","Check the existing account that owns the email (admin Users page) and free it up by changing that account's email first.","If you are re-submitting your own unchanged email, omit the email field from the request body.","In client code, handle the 400 with message 'Email is not available' and prompt the user to choose another address."],"exampleFix":"// before\nawait api.updateMyUser({ email: 'shared@example.com' });\n// after\nconst taken = await isEmailTaken('shared@example.com');\nif (taken) throw new Error('choose a different email');\nawait api.updateMyUser({ email: 'unique@example.com' });","handlingStrategy":"validation","validationCode":"const isEmailTaken = async (email: string) => {\n  const existing = await userRepo.getByEmail(email);\n  return !!existing;\n};\nif (dto.email && await isEmailTaken(dto.email)) {\n  throw new BadRequestException('Email is not available');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await api.updateMyUser({ email });\n} catch (e) {\n  if (e instanceof BadRequestException && e.message === 'Email is not available') {\n    // prompt user to pick another email\n  }\n}","preventionTips":["Always check email availability before submitting an update.","Omit the email field when it hasn't changed.","Normalize/trim emails client-side to avoid false collisions.","In signup forms, enforce uniqueness at input time with a live availability check."],"tags":["email","duplicate","bad-request","user-profile"],"backgroundTag":"user-not-found","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"}