immich-app/immich · error · Exception
No file found for the video
Error message
No file found for the video
What it means
Thrown during video player source initialization in VideoViewerWidget when a localFilePath was supplied but the file does not exist on disk. VideoSource.init with VideoSourceType.file would fail otherwise, so the widget validates existence first with File.exists(). It means the player was handed a path whose backing file was removed or never downloaded.
Solutions
- Check File.existsSync(localFilePath) before initializing the player and fall back to streaming the remote asset instead.
- Trigger a re-download of the asset if the local copy is missing.
- Purge stale localFilePath entries from local storage/DB when files are evicted.
- Handle the exception in the player UI by showing a 'video unavailable' state and retry logic.
Example fix
// before
if (!await file.exists()) {
throw Exception('No file found for the video');
}
// after
if (!await file.exists()) {
// fall back to remote streaming source instead of throwing
return await VideoSource.init(url: widget.asset.remoteUrl, type: VideoSourceType.network);
} Defensive patterns
Strategy: fallback
Validate before calling
final file = File(localFilePath);
if (!await file.exists()) {
// trigger re-download or use remote streaming source
return;
} Type guard
Future<bool> hasLocalFile(String? path) async =>
path != null && await File(path).exists(); Try / catch
try {
final source = await initVideoSource();
// attach player
} catch (e) {
setState(() => playbackError = 'Video file missing; streaming remotely...');
await playFromRemote();
} Prevention
- Verify File.exists() before handing paths to the video player
- Fall back to remote streaming when the local cache misses
- Purge DB/localFilePath entries when cache files are evicted
- Re-download assets whose local files disappeared
When it happens
Trigger: widget.localFilePath is non-null but the file at that path cannot be found — e.g. the local cache was cleared, the asset was deleted, or the path was recorded before the download completed.
Common situations: OS/storage cleaner evicted cached video files; app data cleared between sessions; a stale DB record pointing to a removed temp file; path stored before a cancelled download.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Asset not found or asset is not a video
- Attempted to clear cache, but rmtree is not safe on this…
- Codec ' ' does not support HLS codec strings
- Codec ' ' is unsupported
- acceleration does not support codec ' '. Supported codecs
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/29240cee19bd9322.
Report an issue: GitHub.
Appendix: source
Thrown at mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart:121
}
Future<VideoSource?> _createSource() async {
if (!mounted) {
return null;
}
final videoAsset = await ref.read(assetServiceProvider).getAsset(widget.asset) ?? widget.asset;
if (!mounted) {
return null;
}
try {
final localFilePath = widget.localFilePath;
if (localFilePath != null) {
final file = File(localFilePath);
// ignore: avoid_slow_async_io
if (!await file.exists()) {
throw Exception('No file found for the video');
}
return await VideoSource.init(
path: CurrentPlatform.isAndroid ? file.uri.toString() : file.path,
type: VideoSourceType.file,
);
}
// Attempt to retrieve LocalAsset, falling back to remote if it cannot be found
final localAsset = await _localPlaybackAsset(videoAsset);
if (localAsset != null) {
final file = localAsset.isMotionPhoto
? await StorageRepository().getMotionFileForAsset(localAsset)
: await StorageRepository().getFileForAsset(localAsset.id);
if (!mounted) {
return null;View on GitHub (pinned to e55ac299a4)