{"record":{"id":"fa6319015a3095cb","repo":"immich-app/immich","slug":"editing-live-photos-is-not-supported","errorCode":null,"errorMessage":"Editing live photos is not supported","messagePattern":"Editing live photos is not supported","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"server/src/services/asset.service.ts","lineNumber":540,"sourceCode":"      assetId: id,\n      edits,\n    };\n  }\n\n  async editAsset(auth: AuthDto, id: string, dto: AssetEditsCreateDto): Promise<AssetEditsResponseDto> {\n    await this.requireAccess({ auth, permission: Permission.AssetEditCreate, ids: [id] });\n\n    const asset = await this.assetRepository.getForEdit(id);\n    if (!asset) {\n      throw new BadRequestException('Asset not found');\n    }\n\n    if (asset.type !== AssetType.Image) {\n      throw new BadRequestException('Only images can be edited');\n    }\n\n    if (asset.livePhotoVideoId) {\n      throw new BadRequestException('Editing live photos is not supported');\n    }\n\n    if (isPanorama(asset)) {\n      throw new BadRequestException('Editing panorama images is not supported');\n    }\n\n    if (asset.originalPath?.toLowerCase().endsWith('.gif')) {\n      throw new BadRequestException('Editing GIF images is not supported');\n    }\n\n    if (asset.originalPath?.toLowerCase().endsWith('.svg')) {\n      throw new BadRequestException('Editing SVG images is not supported');\n    }\n\n    // check that crop parameters will not go out of bounds\n    const { width: assetWidth, height: assetHeight } = getDimensions(asset);\n\n    if (!assetWidth || !assetHeight) {","sourceCodeStart":522,"sourceCodeEnd":558,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/asset.service.ts#L522-L558","documentation":"Thrown by editAsset when asset.livePhotoVideoId is set, i.e. the image is the still component of a live/motion photo paired with a video. Because the still and its motion video must stay in sync, the editor refuses to transform only the image, returning 400 BadRequest.","triggerScenarios":"PUT /assets/{id}/edits on an asset that has a non-null livePhotoVideoId (a live photo still).","commonSituations":"User uploads an iOS/Android motion photo and tries to crop or rotate it through the standard image editor; client does not distinguish live photos from plain images.","solutions":["Detect asset.livePhotoVideoId in the UI and disable the editor for live photos.","Offer a separate flow that splits the live photo into a plain still before editing.","Show the user that live-photo editing is intentionally unsupported."],"exampleFix":"// before\nconst editable = asset.type === 'IMAGE';\n\n// after\nconst editable = asset.type === 'IMAGE' && !asset.livePhotoVideoId;","handlingStrategy":"validation","validationCode":"if (asset.livePhotoVideoId) {\n  throw new Error('Live photos cannot be edited as flat images.');\n}\nawait api.put(`/assets/${asset.id}/edits`, { edits });","typeGuard":"const isLivePhoto = (a: { livePhotoVideoId?: string | null }): boolean =>\n  Boolean(a?.livePhotoVideoId);","tryCatchPattern":null,"preventionTips":["Treat livePhotoVideoId as a non-editable flag in the UI.","Surface a 'live photo' badge so users know editing is intentionally blocked.","Split the live photo into a plain still if editing is required."],"tags":["asset","edit","live-photo","validation"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}