{"record":{"id":"9ee0b9628787a0f6","repo":"immich-app/immich","slug":"invalid-user-9ee0b9","errorCode":null,"errorMessage":"Invalid user","messagePattern":"Invalid user","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"server/src/services/partner.service.ts","lineNumber":22,"sourceCode":"import { PartnerCreateDto, PartnerResponseDto, PartnerSearchDto, PartnerUpdateDto } from 'src/dtos/partner.dto.js';\nimport { mapUser } from 'src/dtos/user.dto.js';\nimport { Permission } from 'src/enum.js';\nimport { PartnerDirection, PartnerIds } from 'src/repositories/partner.repository.js';\nimport { BaseService } from 'src/services/base.service.js';\n\n@Injectable()\nexport class PartnerService extends BaseService {\n  async create(auth: AuthDto, { sharedWithId }: PartnerCreateDto): Promise<PartnerResponseDto> {\n    const partnerId: PartnerIds = { sharedById: auth.user.id, sharedWithId };\n    const exists = await this.partnerRepository.get(partnerId);\n    if (exists) {\n      throw new BadRequestException(`Partner already exists`);\n    }\n\n    const user = await this.userRepository.get(sharedWithId, {});\n    if (!user) {\n      this.logger.debug('Partner creation failed: user not found');\n      throw new BadRequestException('Invalid user');\n    }\n\n    const partner = await this.partnerRepository.create(partnerId);\n    return this.mapPartner(partner, PartnerDirection.SharedBy);\n  }\n\n  async remove(auth: AuthDto, sharedWithId: string): Promise<void> {\n    const partnerId: PartnerIds = { sharedById: auth.user.id, sharedWithId };\n    const partner = await this.partnerRepository.get(partnerId);\n    if (!partner) {\n      throw new BadRequestException('Partner not found');\n    }\n\n    await this.partnerRepository.remove(partnerId);\n  }\n\n  async search(auth: AuthDto, { direction }: PartnerSearchDto): Promise<PartnerResponseDto[]> {\n    const partners = await this.partnerRepository.getAll(auth.user.id);","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/partner.service.ts#L4-L40","documentation":"PartnerService.create verifies that the sharedWithId references an existing user via userRepository.get. If the user does not exist, it logs 'Partner creation failed: user not found' and throws BadRequestException('Invalid user'). This prevents dangling partner rows pointing at nonexistent users.","triggerScenarios":"POST /api/partners with a sharedWithId that is not a valid user ID (deleted user, typo, or UUID from another instance).","commonSituations":"Sharing with a user whose account was removed, copy-pasting a stale UUID, sharing with yourself (self not resolvable as expected), or cross-instance IDs after a restore/migration.","solutions":["Confirm the sharedWithId is an existing, active user (GET /api/users) before creating the partner.","Remove the deleted user's stale references or pick a valid user from the user list.","If IDs came from a backup/restore, re-sync the database so user rows exist.","Handle the 400 response in the UI by refreshing the selectable user list."],"exampleFix":"// before\nawait api.partnersApi.createPartner({ sharedWithId: staleUserId });\n// after\nconst users = await api.usersApi.searchUsers();\nconst target = users.find((u) => u.id === sharedWithId);\nif (!target) throw new Error(`User ${sharedWithId} does not exist`);\nawait api.partnersApi.createPartner({ sharedWithId: target.id });","handlingStrategy":"validation","validationCode":"const users = await api.usersApi.searchUsers();\nconst target = users.find((u) => u.id === sharedWithId);\nif (!target) throw new Error(`User ${sharedWithId} not found — refresh user list`);","typeGuard":null,"tryCatchPattern":"try {\n  await api.partnersApi.createPartner({ sharedWithId });\n} catch (e) {\n  if (e.status === 400 && String(e.message).includes('Invalid user')) {\n    await refreshUserList(); // user deleted or wrong ID\n  } else throw e;\n}","preventionTips":["Always populate share targets from a fresh GET /api/users call, never cached UUIDs.","Handle user deletion events by invalidating cached share candidates.","Validate the sharedWithId is a non-empty UUID client-side."],"tags":["user","not-found","partner","bad-request"],"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"}