From 7a4271c85f98cfb4ebbe00e9786d17577330beac Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Wed, 29 Jul 2026 07:31:27 +0200 Subject: Fix video version links being read from stale serialised item data instead of the LinkedChildren table --- Jellyfin.Server.Implementations/Item/BaseItemMapper.cs | 15 +++++++++++++++ .../Item/BaseItemRepository.QueryBuilding.cs | 9 ++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Jellyfin.Server.Implementations/Item/BaseItemMapper.cs b/Jellyfin.Server.Implementations/Item/BaseItemMapper.cs index c64e6ac068..fe202b69ff 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemMapper.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemMapper.cs @@ -134,6 +134,21 @@ public static class BaseItemMapper if (dto is Video video) { video.PrimaryVersionId = entity.PrimaryVersionId; + + // The LinkedChildren table is the source of truth for version links + if (entity.LinkedChildEntities is not null) + { + video.LinkedAlternateVersions = entity.LinkedChildEntities + .Where(e => e.ChildType is Database.Implementations.Entities.LinkedChildType.LinkedAlternateVersion + or Database.Implementations.Entities.LinkedChildType.AutoLinkedAlternateVersion) + .OrderBy(e => e.SortOrder) + .Select(e => new LinkedChild + { + ItemId = e.ChildId, + Type = (MediaBrowser.Controller.Entities.LinkedChildType)e.ChildType + }) + .ToArray(); + } } if (dto is IHasSeries hasSeriesName) diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs index a4de9feb05..3a166979ca 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.QueryBuilding.cs @@ -244,8 +244,8 @@ public sealed partial class BaseItemRepository dbQuery = dbQuery.Include(e => e.Images); } - // Include LinkedChildEntities for container types and videos that use them - // (BoxSet, Playlist, CollectionFolder for manual linking; Video, Movie for alternate versions). + // Include LinkedChildEntities for container types and videos that use them (BoxSet, Playlist, + // CollectionFolder for manual linking; every video type for alternate versions). // When IncludeItemTypes is empty (any type may be returned), always include them to ensure // LinkedChildren are loaded before items are saved back, preventing accidental deletion. var linkedChildTypes = new[] @@ -254,7 +254,10 @@ public sealed partial class BaseItemRepository BaseItemKind.Playlist, BaseItemKind.CollectionFolder, BaseItemKind.Video, - BaseItemKind.Movie + BaseItemKind.Movie, + BaseItemKind.Episode, + BaseItemKind.MusicVideo, + BaseItemKind.Trailer }; if (filter.IncludeItemTypes.Length == 0 || filter.IncludeItemTypes.Any(linkedChildTypes.Contains)) { -- cgit v1.2.3 From 1f4f4acb466153b698284bd31cf27d508fe72cb5 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Wed, 29 Jul 2026 09:39:04 +0200 Subject: Fixup --- Jellyfin.Server.Implementations/Item/BaseItemMapper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jellyfin.Server.Implementations/Item/BaseItemMapper.cs b/Jellyfin.Server.Implementations/Item/BaseItemMapper.cs index fe202b69ff..7f211c9ea7 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemMapper.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemMapper.cs @@ -139,8 +139,8 @@ public static class BaseItemMapper if (entity.LinkedChildEntities is not null) { video.LinkedAlternateVersions = entity.LinkedChildEntities - .Where(e => e.ChildType is Database.Implementations.Entities.LinkedChildType.LinkedAlternateVersion - or Database.Implementations.Entities.LinkedChildType.AutoLinkedAlternateVersion) + // LocalAlternateVersion links belong to Video.LocalAlternateVersions, not here + .Where(e => e.ChildType == Database.Implementations.Entities.LinkedChildType.LinkedAlternateVersion) .OrderBy(e => e.SortOrder) .Select(e => new LinkedChild { -- cgit v1.2.3