{"record":{"id":"f58741da3db9bb45","repo":"immich-app/immich","slug":"partner-not-found","errorCode":null,"errorMessage":"Partner not found","messagePattern":"Partner not found","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"server/src/services/partner.service.ts","lineNumber":33,"sourceCode":"    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);\n    const key = direction === PartnerDirection.SharedBy ? 'sharedById' : 'sharedWithId';\n    return partners\n      .filter((partner): partner is Partner => !!(partner.sharedBy && partner.sharedWith)) // Filter out soft deleted users\n      .filter((partner) => partner[key] === auth.user.id)\n      .map((partner) => this.mapPartner(partner, direction));\n  }\n\n  async update(auth: AuthDto, sharedById: string, dto: PartnerUpdateDto): Promise<PartnerResponseDto> {\n    await this.requireAccess({ auth, permission: Permission.PartnerUpdate, ids: [sharedById] });\n    const partnerId: PartnerIds = { sharedById, sharedWithId: auth.user.id };\n","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/partner.service.ts#L15-L51","documentation":"Thrown by PartnerService.remove when partnerRepository.get(partnerId) returns null. The caller is attempting to unshare from a user they never shared with. BadRequestException -> HTTP 400.","triggerScenarios":"DELETE /partner/{sharedWithId} for a sharedWithId that is not currently a partner of the caller; double-delete after the share was already removed.","commonSituations":"UI state out of sync with server (a partner was removed elsewhere); client retries a delete that already succeeded; user removed from a stale list view.","solutions":["Refresh the partner list before issuing the delete.","Treat 400 'Partner not found' as already-removed success in idempotent delete flows.","Guard the UI so users can only remove partners present in the current list."],"exampleFix":"// before\nconst partner = await this.partnerRepository.get(partnerId);\nif (!partner) {\n  throw new BadRequestException('Partner not found');\n}\n\n// after (DELETE is idempotent)\nconst partner = await this.partnerRepository.get(partnerId);\nif (!partner) {\n  return;\n}","handlingStrategy":"validation","validationCode":"// Confirm the partnership exists before issuing DELETE.\nconst partners = await partnerService.search(auth, { direction: 'shared-by' });\nif (!partners.some((p) => p.id === sharedWithId)) return; // nothing to remove","typeGuard":"const isPartner = (p: PartnerResponseDto | null | undefined): p is PartnerResponseDto =>\n  !!p && typeof p.id === 'string';","tryCatchPattern":"try {\n  await partnerService.remove(auth, sharedWithId);\n} catch (e) {\n  if (e instanceof BadRequestException && /not found/i.test(e.message)) {\n    // already removed: idempotent success\n    return;\n  }\n  throw e;\n}","preventionTips":["Treat remove as idempotent; swallow 'Partner not found' as success.","Refresh the partner list before issuing delete.","Lock the UI row while the delete is in flight to prevent double-submits."],"tags":["partner","idempotency","nestjs","validation"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}