{"record":{"id":"bbdbd8880f6413dd","repo":"immich-app/immich","slug":"cannot-merge-a-person-into-themselves","errorCode":null,"errorMessage":"Cannot merge a person into themselves","messagePattern":"Cannot merge a person into themselves","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"server/src/services/person.service.ts","lineNumber":593,"sourceCode":"  @OnJob({ name: JobName.PersonFileMigration, queue: QueueName.Migration })\n  async handlePersonMigration({ ownerId, personGroupId }: JobOf<JobName.PersonFileMigration>): Promise<JobStatus> {\n    const person = await this.personRepository.getByGroupId({ ownerId, personGroupId });\n    if (!person) {\n      return JobStatus.Failed;\n    }\n\n    await this.storageCore.movePersonFile(person, PersonPathType.Face);\n\n    return JobStatus.Success;\n  }\n\n  async mergePeople(auth: AuthDto, { ids }: MergePersonDto): Promise<BulkIdResponseDto[]> {\n    if (ids.length < 2) {\n      throw new BadRequestException('At least two people are required for merging');\n    }\n\n    if (new Set(ids).size !== ids.length) {\n      throw new BadRequestException('Cannot merge a person into themselves');\n    }\n\n    const results: BulkIdResponseDto[] = [];\n\n    const allowedIds = await this.checkAccess({ auth, permission: Permission.PersonMerge, ids });\n\n    const peopleMap: Record<string, Selectable<PersonTable>[]> = {};\n\n    for (const mergePerson of await this.personRepository.getForMergePerson(ids)) {\n      if (!peopleMap[mergePerson.personGroupId]) {\n        peopleMap[mergePerson.personGroupId] = [];\n      }\n      peopleMap[mergePerson.personGroupId].push(mergePerson);\n    }\n\n    const targetPeople: Record<string, Selectable<PersonTable>> = {};\n    for (const mergeId of ids) {\n      const hasAccess = allowedIds.has(mergeId);","sourceCodeStart":575,"sourceCodeEnd":611,"githubUrl":"https://github.com/immich-app/immich/blob/f48d4b332127ad365ba256108799ca8f571d2dd5/server/src/services/person.service.ts#L575-L611","documentation":"mergePeople rejects an ids array containing duplicates, since merging a person into itself is a no-op and would corrupt the bulk-id response contract. It compares Set size to array length and throws BadRequestException('Cannot merge a person into themselves') when they differ.","triggerScenarios":"POST merge with duplicate IDs in the ids array — e.g. ids: [\"a\", \"a\"], or the primary person's own ID repeated in the body list.","commonSituations":"Client selection logic adding the same person twice (double-click, not de-duplicating), or scripts merging a person into itself thinking it renames/keeps the primary.","solutions":["De-duplicate the ids array before calling: [...new Set(ids)].","Exclude the primary person's ID from the ids payload; the URL already identifies the primary.","Fix selection UI to prevent picking the same person twice.","If you intended to change the primary person, use the person update endpoint instead of merge."],"exampleFix":"// before\nawait api.peopleApi.mergePerson({ id: primaryId, mergePersonDto: { ids: [dupA, dupA, primaryId] } });\n// after\nconst ids = [...new Set([dupA, dupA, primaryId])].filter((id) => id !== primaryId);\nawait api.peopleApi.mergePerson({ id: primaryId, mergePersonDto: { ids } });","handlingStrategy":"validation","validationCode":"const deduped = [...new Set(ids)];\nif (deduped.length !== ids.length) throw new Error('Duplicate person IDs in merge request');","typeGuard":"function hasNoDuplicates(ids) {\n  return Array.isArray(ids) && new Set(ids).size === ids.length;\n}","tryCatchPattern":"try {\n  await api.peopleApi.mergePerson({ id: primaryId, mergePersonDto: { ids } });\n} catch (e) {\n  if (e.status === 400 && String(e.message).includes('merge a person into themselves')) {\n    ids = [...new Set(ids)].filter((id) => id !== primaryId); // retry once deduped\n  } else throw e;\n}","preventionTips":["Always deduplicate ids with Set before merging.","Exclude the primary person's ID from the body payload.","Use single-select components that cannot add the same person twice."],"tags":["merge","people","duplicate","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"f48d4b332127ad365ba256108799ca8f571d2dd5","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}