Fix infinite metadata pruning loop on rclone/network mounts

This fixes issue #15904 where files on rclone network mounts were
repeatedly flagged as 'changed' during library scans, causing Jellyfin
to continuously prune and re-extract metadata in an infinite loop.

The fix changes the file modification detection to require BOTH:
1. Timestamp differs by >1 second
2. File size differs

This prevents false positives from timestamp jitter on network/FUSE
file systems while still correctly detecting legitimate file changes.
This commit is contained in:
ZeusCraft10 2025-12-31 04:06:06 -05:00
parent d28ee6d714
commit 9843f6783c
2 changed files with 20 additions and 13 deletions

View file

@ -164,6 +164,7 @@
- [XVicarious](https://github.com/XVicarious)
- [YouKnowBlom](https://github.com/YouKnowBlom)
- [ZachPhelan](https://github.com/ZachPhelan)
- [ZeusCraft10](https://github.com/ZeusCraft10)
- [KristupasSavickas](https://github.com/KristupasSavickas)
- [Pusta](https://github.com/pusta)
- [nielsvanvelzen](https://github.com/nielsvanvelzen)

View file

@ -336,26 +336,32 @@ namespace MediaBrowser.Providers.Manager
if (!string.IsNullOrEmpty(itemPath))
{
var info = FileSystem.GetFileSystemInfo(itemPath);
if (info.Exists && item.HasChanged(info.LastWriteTimeUtc))
if (info.Exists)
{
Logger.LogDebug("File modification time changed from {Then} to {Now}: {Path}", item.DateModified, info.LastWriteTimeUtc, itemPath);
var timestampChanged = Math.Abs((item.DateModified - info.LastWriteTimeUtc).TotalSeconds) > 1;
var sizeChanged = !info.IsDirectory && item.Size.HasValue && item.Size.Value != info.Length;
item.DateModified = info.LastWriteTimeUtc;
if (ServerConfigurationManager.GetMetadataConfiguration().UseFileCreationTimeForDateAdded)
if (timestampChanged && sizeChanged)
{
if (info.CreationTimeUtc > DateTime.MinValue)
Logger.LogDebug("File modification time changed from {Then} to {Now}: {Path}", item.DateModified, info.LastWriteTimeUtc, itemPath);
item.DateModified = info.LastWriteTimeUtc;
if (ServerConfigurationManager.GetMetadataConfiguration().UseFileCreationTimeForDateAdded)
{
item.DateCreated = info.CreationTimeUtc;
if (info.CreationTimeUtc > DateTime.MinValue)
{
item.DateCreated = info.CreationTimeUtc;
}
}
}
if (item is Video video)
{
Logger.LogInformation("File changed, pruning extracted data: {Path}", item.Path);
ExternalDataManager.DeleteExternalItemDataAsync(video, CancellationToken.None).GetAwaiter().GetResult();
}
if (item is Video video)
{
Logger.LogInformation("File changed, pruning extracted data: {Path}", item.Path);
ExternalDataManager.DeleteExternalItemDataAsync(video, CancellationToken.None).GetAwaiter().GetResult();
}
updateType |= ItemUpdateType.MetadataImport;
updateType |= ItemUpdateType.MetadataImport;
}
}
}