• Blog
  • Migrating to v3

Migrating to v3

June 9, 2026

— Immich Team

How to migrate from Immich v2 to Immich v3, and what breaking changes where introduced as part of Immich v3.


Everyone has been busy breaking Immich 😅

This purpose of this document is enumerate all the breaking changes were introduced as part of Immich v3 and provide migration steps when available.

Breaking changes

This release includes a hefty list of breaking changes, most of which were previously deprecated. This post aims to document, explain, and guide users as they upgrade to v3.



Mobile

Legacy timeline

The legacy timeline in the mobile app has been removed.


Environment variables

IMMICH_MACHINE_LEARNING_PING_TIMEOUT

The environment variable IMMICH_MACHINE_LEARNING_PING_TIMEOUT has been removed.

MACHINE_LEARNING_PRELOAD__CLIP

The environment variable MACHINE_LEARNING_PRELOAD__CLIP has been removed.

MACHINE_LEARNING_PRELOAD__FACIAL_RECOGNITION

The environment variable MACHINE_LEARNING_PRELOAD__FACIAL_RECOGNITION has been removed.


Machine learning

Hardware requirements

A bump in numpy now requires x86 CPUs to be in the x86-64-v2 microarchitecture level or higher. This does not mean AVX is required; virtually every mainstream x86 CPU since 2010 meets the x86-64-v2 baseline.


Database

pgvecto.rs

Support for pgvecto.rs has been removed in v3. Using DB_VECTOR_EXTENSION=pgvecto.rs now throws an error.


OAuth

Insecure requests

OAuth http requests now no longer permit insecure requests by default. To keep using insecure requests, set oauth.allowInsecureRequests in admin > system config.

Issuer URL validation

The oauth.issuerUrl system config property was previously only required to be a string. Now, it is required to parse as a valid URL.


Metrics

Metric names

Exported metric names have been updated: underscore (_) in metric names have been replaced with dot/periods (.).


Server jobs

Removed AuditLogCleanup job

The AuditLogCleanup job has been removed.



Error responses

Previous to v3, the server used class-validator for request validation, but starting with v3, the server has migrated to Zod and now sends back a different error response object. Additionally, the correlationId response property has been migrated to the X-Correlation-ID response header.

Old structure

{
  "message": [
    "[comment] Comment must not be provided when type is not COMMENT"
  ],
  "error": "Bad Request",
  "statusCode": 400,
  "correlationId": "dtw6imvq"
}

New structure

{
  "message": "Validation failed",
  "errors": [
     {
        "path": ["comment"],
        "message": "Comment is required when type is COMMENT",
    },
  ]
}

Error messages

Some error messages have been updated to avoid leaking resource existence or permission details. For more details see #28154.


Endpoints

Empty strings

The following endpoints no longer accept empty strings as a substitute for null.

Previous to v3 adding an asset to a shared link (without being logged in) required two API requests: one to upload the asset and another one to add it to the shared link. Now, assets are automatically added to the associated shared link when they are uploaded, removing the need to shared link access to the following APIs, which have been removed:

  • addAssetsToAlbum (PUT /albums/:id/assets)
  • addAssetsToAlbums (PUT /albums/assets)
  • addSharedLinkAssets (PUT /shared-links/:id/assets)

Endpoints that require shared link authentication now no longer accept query.password. Instead, it should be send as body.password in the sharedLinkLogin (POST /shared-links) endpoint to login, receive a cookie, and use that with subsequent requests.

getAllAlbums

The query parameters of the getAllAlbums (GET /albums) endpoint have been updated. shared has been renamed to isShared and a second parameter isOwner has been added. They now function as follows:

For more details refer to #28213.

createAlbum, updateAlbumInfo, getAllAlbums, etc. (AlbumResponseDto)

Endpoints that return the AlbumResponseDto schema have the following changes:

  • The ownerand ownerId properties have been removed (moved to albumUsers with a role of owner)
  • The assets property has been removed (use POST /api/search/assets instead)

AssetMediaCreateDto

  • The deviceId and deviceAssetId properties of AssetMediaCreateDto have been removed.

AssetResponseDto

  • The deviceId and deviceAssetId properties of AssetResponseDto have been removed.
  • The duration property now returns a number and can be null (represents milliseconds)
  • The unassignedFaces property has been removed (use GET /faces to retrieve asset face information)
  • The width and height properties have been changed from number to integer

ExifResponseDto

  • The exifImageWidth, exifImageHeight, iso, and rating properties have been changed from number to integer

PersonSearchDto

  • The page and size properties have been changed from number to integer

*SearchDto

  • The page and size properties have been changed from number to integer
  • The rating property has been changed from number to integer

SharedLinkEditDto

  • The changeExpiryTime property of SharedLinkEditDto has been removed (instead send expiresAt with a null value)

SharedLinkResponse

The token response property of SharedLinkResponse has been removed.

AudioCodec

  • The libopus value has been removed (use opus instead)

Endpoints (removed)

replaceAssest

The replaceAsset endpoint (PUT /assets/:id/original) has been removed. The API Key permission for this endpoint, asset.replace, has also been removed.

getRandom

The getRandom endpoint (GET /assets/random) has been removed.

getDeltaSync

The getDeltaSync endpoint (POST /sync/delta-sync) has been removed.

getFullSyncForUser

The getFullSyncForUser endpoint POST /sync/full-sync has been removed.

getTheme

The getTheme endpoint (GET /server/theme) has been removed.

checkExistingAssets

The checkExistingAssets endpoint (POST /assets/exists) has been removed.

getAllUserAssetsByDeviceId

The getAllUserAssetsByDeviceId endpoint (GET /assets/device/:deviceId) has been removed.


Cheers,
The Immich Team