immich-app/immich · error · BadRequestException

SyncRequestType.AssetsV1 is deprecated, use SyncRequestType.

Error message

SyncRequestType.AssetsV1 is deprecated, use SyncRequestType.AssetsV2 instead

What it means

Thrown (as BadRequestException) by SyncService.syncAssetsV1, which is now a stub: the AssetsV1 sync stream was removed and unconditionally throws. Clients must request SyncRequestType.AssetsV2. This is a hard deprecation, not a graceful fallback.

Source

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

    }
  }

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

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

  private syncAssetsV1(): Promise<void> {
    throw new BadRequestException('SyncRequestType.AssetsV1 is deprecated, use SyncRequestType.AssetsV2 instead');
  }

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

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

  private syncPartnerAssetsV1(): Promise<void> {
    throw new BadRequestException(

View on GitHub (pinned to 199723261c)

Solutions

  1. Remove SyncRequestType.AssetsV1 from the client's requested types and request AssetsV2 instead.
  2. Update the Immich client (mobile/web) to a release that emits AssetsV2.
  3. Regenerate the SDK from the current openapi.json and recompile.

Example fix

// before
types: [SyncRequestType.AssetsV1]
// after
types: [SyncRequestType.AssetsV2]
Defensive patterns

Strategy: validation

Validate before calling

const requested = [SyncRequestType.AssetsV1].filter(t => t !== SyncRequestType.AssetsV1);
requested.push(SyncRequestType.AssetsV2);
await syncApi.stream({ types: requested });

Type guard

function isV1AssetRequest(types: SyncRequestType[]): boolean {
  return types.includes(SyncRequestType.AssetsV1);
}

Prevention

When it happens

Trigger: GET /sync/stream with a SyncRequestType including SyncRequestType.AssetsV1 in the request types array.

Common situations: Old mobile/desktop client built against a pre-V2 server; cached client config still lists AssetsV1; integration test fixtures not updated after upgrade.

Related errors


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