immich-app/immich · warning
Unable to find existing motion video asset for
Error message
Unable to find existing motion video asset for ${asset.id}: ${asset.originalPath} What it means
This is a warning (not a throw) logged by applyMotionPhotos when, after a checksum conflict was detected and re-lookup was attempted, no existing motion video asset can be found for the photo asset. Motion photo handling (Apple Live Photo / Samsung Motion Photo) expects a paired video asset to already exist or be creatable; if the checksum-based lookup returns nothing, the pairing is abandoned for that asset and the job returns early. The photo is left unpaired with its motion video.
Solutions
- Re-run the metadata extraction job for the affected asset — the race is often transient and a second pass will find or create the motion asset.
- Verify the motion video file still exists on disk at the path derived from the photo's sidecar/adjacent file and that its checksum matches what was queried.
- Check for and delete orphaned/partially-created asset rows (asset with the checksum missing or in a conflicting library) via the database or admin tooling.
- Ensure only one server instance / one library-scan worker processes the same library at a time to avoid insert races.
Example fix
// before
motionAsset = await this.assetRepository.getByChecksum(checksumQuery);
if (!motionAsset) {
this.logger.warn(`Unable to find existing motion video asset for ${asset.id}: ${asset.originalPath}`);
return;
}
// after
motionAsset = await this.assetRepository.getByChecksum(checksumQuery);
if (!motionAsset) {
this.logger.warn(`Unable to find existing motion video asset for ${asset.id}: ${asset.originalPath}; retrying lookup without library scope`);
motionAsset = await this.assetRepository.getByChecksum({ checksum });
if (!motionAsset) return;
} Defensive patterns
Strategy: fallback
Validate before calling
// before enqueuing extraction, verify the motion video file exists
const motionPath = getMotionVideoPath(asset.originalPath);
if (!motionPath || !fs.existsSync(motionPath)) {
this.logger.warn(`Skipping motion pairing: missing motion video for ${asset.id}`);
return JobStatus.Skipped;
} Type guard
const isAsset = (a: AssetResponse | null | undefined): a is AssetResponse => !!a && typeof a.id === 'string' && typeof a.checksum === 'string';
Try / catch
try {
await this.applyMotionPhotos(asset, exifData);
} catch (error) {
this.logger.warn(`Motion photo pairing failed for ${asset.id}: ${error}`);
return JobStatus.Failed;
} Prevention
- Avoid running multiple extraction workers over the same library concurrently to prevent checksum insert races.
- After any bulk delete or library re-scan, re-run metadata extraction so pairings are rebuilt.
- Monitor for 'Unable to find existing motion video asset' warnings and reconcile orphaned assets periodically.
- Keep motion-video sidecar files together with their photos when moving or syncing libraries.
When it happens
Trigger: Job handleMetadataExtraction processes an asset whose metadata indicates a motion photo; the initial insert of the motion asset hits a unique checksum constraint error, so the code re-queries assetRepository.getByChecksum(checksumQuery), and that query returns null (the conflicting asset is not visible or was concurrently deleted).
Common situations: Concurrent metadata-extraction jobs racing on the same motion video file; a checksum-constraint error caused by an asset in a state that the follow-up query does not match (e.g. different library/visibility scope in the query); orphaned or deleted motion assets after partial cleanup; libraries re-scanned with changed storage layout.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Asset dimensions are not available for editing
- Asset not in stack
- Cannot remove stack's primary asset
- Could not find asset
- Crop action must be the first edit action
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/b52566ca3de48b8f.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/metadata.service.ts:753
ownerId: asset.ownerId,
originalPath: StorageCore.getAndroidMotionPath(asset, motionAssetId),
originalFileName: `${parse(asset.originalFileName).name}.mp4`,
visibility: AssetVisibility.Hidden,
});
isNewMotionAsset = true;
if (!asset.isExternal) {
await this.userRepository.updateUsage(asset.ownerId, video.byteLength);
}
} catch (error) {
if (!isAssetChecksumConstraint(error)) {
throw error;
}
motionAsset = await this.assetRepository.getByChecksum(checksumQuery);
if (!motionAsset) {
this.logger.warn(`Unable to find existing motion video asset for ${asset.id}: ${asset.originalPath}`);
return;
}
}
}
if (!isNewMotionAsset) {
this.logger.debugFn(() => {
const base64Checksum = checksum.toString('base64');
return `Motion asset with checksum ${base64Checksum} already exists for asset ${asset.id}: ${asset.originalPath}`;
});
}
// Hide the motion photo video asset if it's not already hidden to prepare for linking
if (motionAsset.visibility === AssetVisibility.Timeline) {
await this.assetRepository.update({
id: motionAsset.id,
visibility: AssetVisibility.Hidden,
});View on GitHub (pinned to e55ac299a4)