immich-app/immich · error · BadRequestException

SyncRequestType.AlbumAssetsV1 is deprecated, use…

Error message

SyncRequestType.AlbumAssetsV1 is deprecated, use SyncRequestType.AlbumAssetsV2 instead

What it means

Generic deprecation guard: syncAlbumAssetsV1 unconditionally throws for sync requests using the legacy SyncRequestType.AlbumAssetsV1 protocol, forcing clients onto AlbumAssetsV2 which uses backfill checkpoints (sendEntityBackfillCompleteAck / upsertBackfillCheckpoint) instead of the old ack scheme. The error is a protocol-cutover signal, not a data problem; the at-fault input is the deprecated SyncRequestType.AlbumAssetsV1 query parameter.

Solutions

  1. Update the Immich mobile app to an AlbumAssetsV2-capable version
  2. Replace AlbumAssetsV1 with SyncRequestType.AlbumAssetsV2 in the sync request

Example fix

// before
requests: [{ type: SyncRequestType.AlbumAssetsV1 }]
// after
requests: [{ type: SyncRequestType.AlbumAssetsV2 }]
Defensive patterns

Strategy: validation

Validate before calling

if (requests.some(r => r.type === SyncRequestType.AlbumAssetsV1)) throw new Error('Use AlbumAssetsV2');

Type guard

null

Try / catch

try {
  await syncStream(requests);
} catch (e) {
  if (e.status === 400 && e.message.includes('AlbumAssetsV1')) {
    requests = requests.map(r => r.type === 'AlbumAssetsV1' ? { ...r, type: 'AlbumAssetsV2' } : r);
  }
}

Prevention

When it happens

Trigger: Client includes SyncRequestType.AlbumAssetsV1 in its sync request; handlers dispatches to syncAlbumAssetsV1 which always throws.

Common situations: Album-heavy workflows on old mobile clients after a server upgrade.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


AI-assisted analysis of immich-app/immich@f48d4b3321 (2026-09-15). Data as JSON: /api/errors/004b29393dd69bf5. Report an issue: GitHub.

Appendix: source

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

        await sendEntityBackfillCompleteAck(response, backfillType, createId);
      }
    } else if (albums.length > 0) {
      await this.upsertBackfillCheckpoint({
        type: backfillType,
        sessionId,
        createId: albums.at(-1)!.createId,
      });
    }

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

  private syncAlbumAssetsV1(): Promise<void> {
    throw new BadRequestException(
      'SyncRequestType.AlbumAssetsV1 is deprecated, use SyncRequestType.AlbumAssetsV2 instead',
    );
  }

  private async syncAlbumAssetsV2(
    options: SyncQueryOptions,
    response: Writable,
    checkpointMap: CheckpointMap,
    sessionId: string,
  ) {
    const backfillType = SyncEntityType.AlbumAssetBackfillV2;
    const backfillCheckpoint = checkpointMap[backfillType];
    const albums = await this.syncRepository.album.getCreatedAfter({
      ...options,
      afterCreateId: backfillCheckpoint?.updateId,
    });
    const updateType = SyncEntityType.AlbumAssetUpdateV2;
    const createType = SyncEntityType.AlbumAssetCreateV2;

View on GitHub (pinned to f48d4b3321)