immich-app/immich · error · BadRequestException

SyncRequestType.AssetFacesV1 is deprecated, use SyncRequestT

Error message

SyncRequestType.AssetFacesV1 is deprecated, use SyncRequestType.AssetFacesV2 instead

What it means

Thrown (as BadRequestException) by SyncService.syncAssetFacesV1, a stub that always rejects. AssetFacesV1 was superseded by AssetFacesV2 and the old stream is disabled.

Source

Thrown at server/src/services/sync.service.ts:843

    }
  }

  private async syncPeopleV1(options: SyncQueryOptions, response: Writable, checkpointMap: CheckpointMap) {
    const deleteType = SyncEntityType.PersonDeleteV1;
    const deletes = this.syncRepository.person.getDeletes({ ...options, ack: checkpointMap[deleteType] });
    for await (const { id, ...data } of deletes) {
      send(response, { type: deleteType, ids: [id], data });
    }

    const upsertType = SyncEntityType.PersonV1;
    const upserts = this.syncRepository.person.getUpserts({ ...options, ack: checkpointMap[upsertType] });
    for await (const { updateId, ...data } of upserts) {
      send(response, { type: upsertType, ids: [updateId], data });
    }
  }

  private syncAssetFacesV1(): Promise<void> {
    throw new BadRequestException(
      'SyncRequestType.AssetFacesV1 is deprecated, use SyncRequestType.AssetFacesV2 instead',
    );
  }

  private async syncAssetFacesV2(options: SyncQueryOptions, response: Writable, checkpointMap: CheckpointMap) {
    const deleteType = SyncEntityType.AssetFaceDeleteV1;
    const deletes = this.syncRepository.assetFace.getDeletes({ ...options, ack: checkpointMap[deleteType] });
    for await (const { id, ...data } of deletes) {
      send(response, { type: deleteType, ids: [id], data });
    }

    const upsertType = SyncEntityType.AssetFaceV2;
    const upserts = this.syncRepository.assetFace.getUpserts({ ...options, ack: checkpointMap[upsertType] });
    for await (const { updateId, ...data } of upserts) {
      send(response, { type: upsertType, ids: [updateId], data });
    }
  }

View on GitHub (pinned to 199723261c)

Solutions

  1. Replace SyncRequestType.AssetFacesV1 with SyncRequestType.AssetFacesV2.
  2. Upgrade the client to the matched server release.
  3. Regenerate SDK and remove V1 enum usage.

Example fix

// before
types: [SyncRequestType.AssetFacesV1]
// after
types: [SyncRequestType.AssetFacesV2]
Defensive patterns

Strategy: validation

Validate before calling

const types = clientTypes.filter(t => t !== SyncRequestType.AssetFacesV1);
types.push(SyncRequestType.AssetFacesV2);
await syncApi.stream({ types });

Type guard

function requestsAssetFacesV1(types: SyncRequestType[]): boolean {
  return types.includes(SyncRequestType.AssetFacesV1);
}

Prevention

When it happens

Trigger: GET /sync/stream whose SyncRequestType array includes SyncRequestType.AssetFacesV1.

Common situations: Client built before the V2 face sync; older desktop app on a newer server.

Related errors


AI-assisted analysis of immich-app/immich@199723261c (2026-08-12). Data as JSON: /api/errors/a94c6744aa82f3e4. Report an issue: GitHub.