{"record":{"id":"1df72b73bfb5a5a7","repo":"immich-app/immich","slug":"live-photo-video-not-found","errorCode":null,"errorMessage":"Live photo video not found","messagePattern":"Live photo video not found","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/utils/asset.util.ts","lineNumber":151,"sourceCode":"    if (timelineEnabled && !partner.inTimeline) {\n      continue;\n    }\n\n    partnerIds.add(partner.sharedById);\n  }\n\n  return [...partnerIds];\n};\n\nexport type AssetHookRepositories = { asset: AssetRepository; event: EventRepository };\n\nexport const onBeforeLink = async (\n  { asset: assetRepository, event: eventRepository }: AssetHookRepositories,\n  { userId, livePhotoVideoId }: { userId: string; livePhotoVideoId: string },\n) => {\n  const motionAsset = await assetRepository.getById(livePhotoVideoId);\n  if (!motionAsset) {\n    throw new BadRequestException('Live photo video not found');\n  }\n  if (motionAsset.type !== AssetType.Video) {\n    throw new BadRequestException('Live photo video must be a video');\n  }\n  if (motionAsset.ownerId !== userId) {\n    throw new BadRequestException('Live photo video does not belong to the user');\n  }\n\n  if (motionAsset && motionAsset.visibility === AssetVisibility.Timeline) {\n    await assetRepository.update({ id: livePhotoVideoId, visibility: AssetVisibility.Hidden });\n    await eventRepository.emit('AssetHide', { assetId: motionAsset.id, userId });\n  }\n};\n\nexport const onBeforeUnlink = async (\n  { asset: assetRepository }: AssetHookRepositories,\n  { livePhotoVideoId }: { livePhotoVideoId: string },\n) => {","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/utils/asset.util.ts#L133-L169","documentation":"Thrown by onBeforeLink when linking a live photo's motion (video) component to an asset, but no asset exists for the provided livePhotoVideoId. Immich requires the motion video to be an existing asset before it can be attached to the image asset. This prevents dangling references to non-existent assets.","triggerScenarios":"Calling asset link (onBeforeLink) with a livePhotoVideoId that was deleted, never uploaded, or belongs to a different Immich server/instance.","commonSituations":"Mobile client uploads a live photo pair where the video part failed to upload; user deleted the motion video but the client still references its ID; syncing clients with stale IDs after a database restore.","solutions":["Verify the livePhotoVideoId references an existing asset via GET /api/assets/:id","Re-upload the missing motion video component and retry the link","Check the client is pointing at the correct server (asset IDs are not portable across instances)","Clear stale client-side cache of live photo pairs and re-pair assets"],"exampleFix":"// before\nawait onBeforeLink(repos, { userId, livePhotoVideoId: staleId });\n// after\nconst motion = await assetRepository.getById(staleId);\nif (!motion) {\n  console.warn(`Motion asset ${staleId} missing; re-uploading before link`);\n  const fresh = await uploadMotionVideo(pair);\n  await onBeforeLink(repos, { userId, livePhotoVideoId: fresh.id });\n}","handlingStrategy":"validation","validationCode":"const motion = await api.getAsset(livePhotoVideoId);\nif (!motion) throw new Error(`Motion asset ${livePhotoVideoId} not found; re-upload before linking`);","typeGuard":null,"tryCatchPattern":"try {\n  await linkLivePhoto(assetId, livePhotoVideoId);\n} catch (e) {\n  if (e.status === 400 && /not found/.test(e.message)) {\n    // re-upload motion video and retry link\n  }\n}","preventionTips":["Resolve live photo pair IDs right before linking, not from long-lived cache","Handle failed video uploads before attempting the link","Use server-provided pairing metadata from the upload response"],"tags":["asset","live-photo","not-found"],"backgroundTag":"entity-not-found","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}