immich-app/immich · error · BadRequestException
Editing live photos is not supported
Error message
Editing live photos is not supported
What it means
editAsset rejects live photos: if the asset has a livePhotoVideoId (the paired video component), throwing BadRequestException('Editing live photos is not supported'). Image transforms like crop/rotate are not applied to the paired video, so the operation is blocked to avoid inconsistent results.
Solutions
- Detect live photos (livePhotoVideoId present in the asset response) and skip them in edit flows
- Inform users that live photos cannot be edited and offer to edit only the still part if the API allows
- Exclude assets with livePhotoVideoId from bulk edit selections
- If editing the still is essential, duplicate/export the still frame as a standalone image and edit that
Example fix
// before
await applyEdits(asset.id, edits);
// after
if (asset.livePhotoVideoId) {
skippedLivePhotos.push(asset.id);
return;
}
await applyEdits(asset.id, edits); Defensive patterns
Strategy: validation
Validate before calling
if (asset.livePhotoVideoId) throw new Error(`Asset ${asset.id} is a live photo; editing not supported`); Type guard
const isLivePhoto = (a: { livePhotoVideoId?: string | null }) => !!a.livePhotoVideoId; Try / catch
try { await api.applyEdits(id, edits); } catch (e) { if (String(e?.response?.data?.message).includes('live photos')) { skippedLivePhotos.add(id); return; } throw e; } Prevention
- Exclude assets with livePhotoVideoId from edit selections
- Surface a live-photo badge in the edit UI
- Bulk tools should prefetch asset details and split live photos out
- Keep iOS imports flagged so downstream jobs can skip them
When it happens
Trigger: Submitting image edits for an iOS live photo where asset.livePhotoVideoId is set, e.g. PUT crop/rotate edits on a Live Photo asset.
Common situations: Bulk editing an iPhone library where many assets are live photos; clients not exposing a live-photo distinction in their UI; sync tools applying saved edits uniformly across a library.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Editing panorama images is not supported
- Cannot unlink Android motion photos
- Editing GIF images is not supported
- Editing SVG images is not supported
- Live photo video must be a video
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/fa6319015a3095cb.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/asset.service.ts:545
assetId: id,
edits,
};
}
async editAsset(auth: AuthDto, id: string, dto: AssetEditsCreateDto): Promise<AssetEditsResponseDto> {
await this.requireAccess({ auth, permission: Permission.AssetEditCreate, ids: [id] });
const asset = await this.assetRepository.getForEdit(id);
if (!asset) {
throw new BadRequestException('Asset not found');
}
if (asset.type !== AssetType.Image) {
throw new BadRequestException('Only images can be edited');
}
if (asset.livePhotoVideoId) {
throw new BadRequestException('Editing live photos is not supported');
}
if (isPanorama(asset)) {
throw new BadRequestException('Editing panorama images is not supported');
}
if (asset.originalPath?.toLowerCase().endsWith('.gif')) {
throw new BadRequestException('Editing GIF images is not supported');
}
if (asset.originalPath?.toLowerCase().endsWith('.svg')) {
throw new BadRequestException('Editing SVG images is not supported');
}
// check that crop parameters will not go out of bounds
const { width: assetWidth, height: assetHeight } = getDimensions(asset);
if (!assetWidth || !assetHeight) {View on GitHub (pinned to e55ac299a4)