immich-app/immich · warning · BadRequestException
At least two people are required for merging
Error message
At least two people are required for merging
What it means
mergePeople requires at least two person IDs because merging means collapsing one or more source people into a primary. With fewer than two IDs there is nothing to merge, so it throws BadRequestException('At least two people are required for merging') before any access checks.
Solutions
- Include at least two person IDs: the primary person (in the URL) plus at least one source person in the ids array.
- Select the duplicate people in the UI before clicking merge.
- Fix client scripts to validate ids.length >= 2 before calling the API.
- If you only have one person, there is nothing to merge — remove the duplicate expectation from your workflow.
Example fix
// before
await api.peopleApi.mergePerson({ id: primaryId, mergePersonDto: { ids: [primaryId] } }); // 1 id -> 400
// after
const ids = [duplicateId1, duplicateId2];
if (ids.length >= 2) {
await api.peopleApi.mergePerson({ id: primaryId, mergePersonDto: { ids } });
} Defensive patterns
Strategy: validation
Validate before calling
if (!Array.isArray(ids) || ids.length < 2) {
throw new Error('Select at least two people to merge');
} Try / catch
try {
await api.peopleApi.mergePerson({ id: primaryId, mergePersonDto: { ids } });
} catch (e) {
if (e.status === 400 && String(e.message).includes('At least two people are required')) {
// re-open selection UI
} else throw e;
} Prevention
- Disable the merge button until >= 2 people are selected.
- Validate ids.length >= 2 client-side before every merge call.
- Remember the primary person goes in the URL, sources go in the body.
When it happens
Trigger: POST /api/people/{id}/merge (or the merge endpoint) with a MergePersonDto whose ids array has 0 or 1 entries — e.g. only the primary person selected with no sources, or an empty selection.
Common situations: UI state where checkboxes were cleared before submitting, API scripts calling merge with a single ID, or client bugs sending ids=[primaryId] only.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Cannot merge a person into themselves
- assetIds, albumId, or userId is required
- Cannot request to join your own cluster group
- error instanceof Error ? error.message : error
- {error.message}
AI-assisted analysis of immich-app/immich@f48d4b3321 (2026-09-15).
Data as JSON: /api/errors/864dae4179f5d240.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/person.service.ts:589
return JobStatus.Success;
}
@OnJob({ name: JobName.PersonFileMigration, queue: QueueName.Migration })
async handlePersonMigration({ ownerId, personGroupId }: JobOf<JobName.PersonFileMigration>): Promise<JobStatus> {
const person = await this.personRepository.getByGroupId({ ownerId, personGroupId });
if (!person) {
return JobStatus.Failed;
}
await this.storageCore.movePersonFile(person, PersonPathType.Face);
return JobStatus.Success;
}
async mergePeople(auth: AuthDto, { ids }: MergePersonDto): Promise<BulkIdResponseDto[]> {
if (ids.length < 2) {
throw new BadRequestException('At least two people are required for merging');
}
if (new Set(ids).size !== ids.length) {
throw new BadRequestException('Cannot merge a person into themselves');
}
const results: BulkIdResponseDto[] = [];
const allowedIds = await this.checkAccess({ auth, permission: Permission.PersonMerge, ids });
const peopleMap: Record<string, Selectable<PersonTable>[]> = {};
for (const mergePerson of await this.personRepository.getForMergePerson(ids)) {
if (!peopleMap[mergePerson.personGroupId]) {
peopleMap[mergePerson.personGroupId] = [];
}
peopleMap[mergePerson.personGroupId].push(mergePerson);
}View on GitHub (pinned to f48d4b3321)