July 1, 2026
— Immich Team
How to migrate from Immich v2 to Immich v3, and what breaking changes where introduced as part of Immich v3.
The purpose of this document is enumerate all the breaking changes that were introduced as part of Immich v3 and provide migration steps when available.
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. Found something missing? Let us know and we'll get it fixed.
The legacy timeline in the mobile app has been removed. If you still experience issues with the new timeline, please open an issue on GitHub so we can take a look.
IMMICH_MACHINE_LEARNING_PING_TIMEOUTUse the machineLearning.availabilityChecks.timeout system config instead (Admin UI)
MACHINE_LEARNING_PRELOAD__CLIPUse the MACHINE_LEARNING_PRELOAD__CLIP__TEXTUAL and MACHINE_LEARNING_PRELOAD__CLIP__VISUAL environment variables instead
MACHINE_LEARNING_PRELOAD__FACIAL_RECOGNITIONUse the MACHINE_LEARNING_PRELOAD__FACIAL_RECOGNITION__DETECTION and MACHINE_LEARNING_PRELOAD__FACIAL_RECOGNITION__RECOGNITION environment variables instead
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.
Support for pgvecto.rs has been removed in v3. Using DB_VECTOR_EXTENSION=pgvecto.rs now throws an error.
We recommend migrating to VectorChord, which is the successor of pgvecto.rs. For information about how to migrate, you can read the documentation
OAuth http requests now no longer permit insecure requests by default. To keep using insecure requests, set oauth.allowInsecureRequests in admin > system config.
The oauth.issuerUrl system config property was previously only required to be a string. Now, it is required to parse as a valid URL.
Exported metric names have been updated: underscore (_) in metric names have been replaced with dot/periods (.).
AuditLogCleanup jobThe AuditLogCleanup job has been removed.
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.
{
"message": [
"[comment] Comment must not be provided when type is not COMMENT"
],
"error": "Bad Request",
"statusCode": 400,
"correlationId": "dtw6imvq"
}{
"message": "Validation failed",
"errors": [
{
"path": ["comment"],
"message": "Comment is required when type is COMMENT",
},
]
}Some error messages have been updated to avoid leaking resource existence or permission details. For more details see #28154.
POST /assets / uploadAssetdeviceId and deviceAssetId properties of AssetMediaCreateDto have been removed.duration property must now be a number and can be null (represents milliseconds)AssetResponseDtoEndpoints that return assets have been updated with the following changes:
deviceId and deviceAssetId properties of AssetResponseDto have been removed.duration property now returns a number and can be null (represents milliseconds)unassignedFaces property has been removed (use GET /faces to retrieve asset face information)width and height properties have been changed from number to integerExifResponseDtoEndpoints that return exif have been updated with the following changes:
exifImageWidth, exifImageHeight, iso, and rating properties have been changed from number to integerGET /albums / getAllAlbumsThe query parameters of the getAllAlbums endpoint have been updated. shared has been renamed to isShared and a second parameter isOwned has been added. They now function as follows:
For more details refer to #28213.
AlbumResponseDtoEndpoints that return albums have been updated with the following changes:
ownerand ownerId properties have been removed (moved to albumUsers with a role of owner)assets property has been removed (use POST /api/search/metadata instead)GET /people / getAllPeoplepage and size properties have been changed from number to integerPOST /search/* / search*Search endpoints have been updated with the following changes:
page and size properties have been changed from number to integerrating property has been changed from number to integervisibility is omitted it now defaults to any visibility (except for locked, if the session is not elevated), instead of timeline visibility.PATCH /shared-links/:id / updateSharedLinkchangeExpiryTime property of SharedLinkEditDto has been removed (instead send expiresAt with a null value)
PUT /system-config / updateConfiglibopus value of AudioCodec has been removed (use opus instead)Endpoints that require shared link authentication now no longer accept query.password. Instead, it should be send as body.password in the POST /shared-links/login / sharedLinkLogin endpoint to login, receive a cookie, and use that with subsequent requests.
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, to which the access has been removed:
PUT /albums/:id/assets / addAssetsToAlbumPUT /albums/assets / addAssetsToAlbumsPUT /shared-links/:id/assets / addSharedLinkAssetsThe token response property of SharedLinkResponse has been removed.
The following endpoints no longer accept empty strings as a substitute for null.
PUT /assets/:id/original replaceAssetasset.replace, has also been removed.PUT /assets/:id/clone / copyAsset instead.GET /assets/random / getRandomPOST /search/random / searchRandom instead.POST /sync/delta-sync / getDeltaSyncPOST /sync/full-sync / getFullSyncForUserGET /server/theme / getThemeGET /custom.css insteadPOST /assets/exists / checkExistingAssetsGET /assets/device/:deviceId / getAllUserAssetsByDeviceIdCheers,
The Immich Team