Skip to content

Fix IsPlayed and IsUnplayed sorting for shows and collections - #17713

Merged
crobibero merged 1 commit into
jellyfin:masterfrom
LTe:fix/sort-isplayed-series
Aug 25, 2026
Merged

crobibero merged 1 commit into
jellyfin:masterfrom
LTe:fix/sort-isplayed-series

Conversation

@LTe

@LTe LTe commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Changes

The IsPlayed and IsUnplayed sort options do not work for shows and collections. They stay in the unplayed group however much of them has been played, and flipping sortOrder returns the very same list. Only movies sort correctly.

Six shows, Alpha Show and Foxtrot Show fully played. Before:

$ curl "https://jellyfin.example.com/Items?userId=USER_ID&includeItemTypes=Series&recursive=true&fields=UserData&sortBy=IsPlayed&sortOrder=Ascending" | jq -r '.Items[] | "\(.UserData.Played)\t\(.Name)"'
true	Alpha Show
false	Bravo Show
false	The Charlie Show
false	Delta Show
false	Echo Show
true	Foxtrot Show

Passing sortOrder=Descending returns that same list, unchanged, which is what gives the bug away. The key evaluates to the same value for every show, so there is nothing for the direction to reverse.

$ curl "https://jellyfin.example.com/Items?userId=USER_ID&includeItemTypes=Series&recursive=true&fields=UserData&sortBy=IsPlayed&sortOrder=Descending" | jq -r '.Items[] | "\(.UserData.Played)\t\(.Name)"'
true	Alpha Show
false	Bravo Show
false	The Charlie Show
false	Delta Show
false	Echo Show
true	Foxtrot Show

After:

$ curl "https://jellyfin.example.com/Items?userId=USER_ID&includeItemTypes=Series&recursive=true&fields=UserData&sortBy=IsPlayed&sortOrder=Ascending" | jq -r '.Items[] | "\(.UserData.Played)\t\(.Name)"'
false	Bravo Show
false	The Charlie Show
false	Delta Show
false	Echo Show
true	Alpha Show
true	Foxtrot Show

$ curl "https://jellyfin.example.com/Items?userId=USER_ID&includeItemTypes=Series&recursive=true&fields=UserData&sortBy=IsPlayed&sortOrder=Descending" | jq -r '.Items[] | "\(.UserData.Played)\t\(.Name)"'
true	Alpha Show
true	Foxtrot Show
false	Bravo Show
false	The Charlie Show
false	Delta Show
false	Echo Show

This is not a regression. Ordering has read the item's own stored played flag since at least 10.9, where both keys mapped to the same column, and #12798 carried that over to EF Core unchanged.

ItemSortBy.IsPlayed => "played",
ItemSortBy.IsUnplayed => "played",

Filtering got its folder handling back then as a special case, with a note next to it.

// We should probably figure this out for all folders, but for right now, this is the only place where we need it
if (query.IncludeItemTypes.Length == 1 && query.IncludeItemTypes[0] == BaseItemKind.Series)

Filtering has since been generalised to every folder kind. Ordering never was.

Note that no first party client offers these two as a sort option today, the web client exposes played state as a filter only.

Code assistance

Code was written with help of Claude Code.

Issues

Ordering mapped both keys to the item's own stored UserData row. Folders do not
have one: a series, season or box set counts as played when no descendant is
left unplayed, which is what the isPlayed filter and the DTO both report. A
mixed library therefore sorted every series and box set into the unplayed group,
and a query could filter and sort by two different notions of "played".

Extract the filter's predicate into BuildIsPlayedFilter and route both sort keys
through it so the two cannot drift apart again.
@sonarqubecloud

Copy link
Copy Markdown

@LTe LTe changed the title Order IsPlayed and IsUnplayed by the played state the filter reports Fix IsPlayed and IsUnplayed sorting for shows and collections Aug 25, 2026
@LTe
LTe marked this pull request as ready for review August 25, 2026 13:45
@Shadowghost
Shadowghost requested a review from JPVenson August 25, 2026 15:07
@Shadowghost Shadowghost moved this from Todo to Review in Jellyfin v12 Aug 25, 2026
@jellyfin-bot

Copy link
Copy Markdown
Contributor

Jellyfin API (v 12.0.0)


Result


No differences. Specifications are equivalent

@crobibero
crobibero merged commit f3298ee into jellyfin:master Aug 25, 2026
16 checks passed
@github-project-automation github-project-automation Bot moved this from Review to Done in Jellyfin v12 Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants