Latest items under a parent that names nothing answer with nothing #69

Closed
opened 2026-08-04 14:35:16 +02:00 by Claude · 1 comment
Collaborator

/Items/Latest under a parent that names nothing answers with nothing.

request upstream ours
/Items/Latest?ParentId=<unknown>&Limit=16 4 entries 0

UserViewManager.GetItemsForLatestItems (UserViewManager.cs:236-265) resolves
the parent with GetItemById and adds it to parents only where it is a
Folder (or dispatches to the channel manager where it is a Channel). An id
that resolves to nothing takes neither branch, so parents stays empty — and an
empty parents is every library the user can see, not none of them.

This server narrows to the named parent and finds nothing under it.

Same shape as #64, which was about an unknown user: an id upstream cannot
resolve narrows nothing, where this port narrows to something that does not
exist. Worth checking the other routes that take a parentId for the same
pattern while fixing this one — #48 established which of them refuse outright,
and those are not in question.

Accounts for 3 of the 7 differences the browsing scenario reports.

`/Items/Latest` under a parent that names nothing answers with nothing. | request | upstream | ours | |---|---|---| | `/Items/Latest?ParentId=<unknown>&Limit=16` | 4 entries | **0** | `UserViewManager.GetItemsForLatestItems` (`UserViewManager.cs:236-265`) resolves the parent with `GetItemById` and adds it to `parents` only where it is a `Folder` (or dispatches to the channel manager where it is a `Channel`). An id that resolves to nothing takes neither branch, so `parents` stays empty — and an empty `parents` is every library the user can see, not none of them. This server narrows to the named parent and finds nothing under it. Same shape as #64, which was about an unknown *user*: an id upstream cannot resolve narrows nothing, where this port narrows to something that does not exist. Worth checking the other routes that take a `parentId` for the same pattern while fixing this one — #48 established which of them refuse outright, and those are not in question. Accounts for 3 of the 7 differences the `browsing` scenario reports.
Author
Collaborator

Fixed. UserViewManager.cs:270 falls back when the parents list is empty:

if (parents.Count == 0)
{
    parents = GetUserRootFolder().GetChildren(user, true)
        .Where(i => i is Folder)
        .Where(i => !user.GetPreferenceValues<Guid>(LatestItemExcludes).Contains(i.Id))
}

An id that resolves to nothing — and equally one that resolves to something
that is not a folder
— takes neither branch above it, so it is answered over
every library the user can see. Verified live: an unknown id and an episode's id
each give upstream the same 4 entries a request with no parent gives.

The music played-state exemption is now keyed on the parent the request named
rather than on the fallback, which matters: an unknown id widening to a set
containing a music library must still keep the filter.

The audit of every parentId route outside the refusing set of #48:

route verdict
/Items/Latest, /Users/{id}/Items/Latest the bug — fixed
/Shows/NextUp correct, and not the same rule — TVSeriesManager has no fallback, so nothing really is nothing
/UserItems/Resume, /Search/Hints, /Items/Suggestions, /Items/Filters2 already correct
/Years 400 on both, per #48

One regression of mine that it caught. /Persons?ParentId=<unknown> was
answering 400 here where upstream answers 200 with nothing: PersonsController
hands the id to the people query and never resolves it, alone among the by-name
listings. I had over-applied #48's refusal. Fixed separately, with a test.

Fixed. `UserViewManager.cs:270` falls back when the parents list is empty: if (parents.Count == 0) { parents = GetUserRootFolder().GetChildren(user, true) .Where(i => i is Folder) .Where(i => !user.GetPreferenceValues<Guid>(LatestItemExcludes).Contains(i.Id)) } An id that resolves to nothing — **and equally one that resolves to something that is not a folder** — takes neither branch above it, so it is answered over every library the user can see. Verified live: an unknown id and an episode's id each give upstream the same 4 entries a request with no parent gives. The music played-state exemption is now keyed on the parent the request *named* rather than on the fallback, which matters: an unknown id widening to a set containing a music library must still keep the filter. **The audit of every `parentId` route outside the refusing set of #48:** | route | verdict | |---|---| | `/Items/Latest`, `/Users/{id}/Items/Latest` | the bug — fixed | | `/Shows/NextUp` | correct, and *not* the same rule — `TVSeriesManager` has no fallback, so nothing really is nothing | | `/UserItems/Resume`, `/Search/Hints`, `/Items/Suggestions`, `/Items/Filters2` | already correct | | `/Years` | 400 on both, per #48 | **One regression of mine that it caught.** `/Persons?ParentId=<unknown>` was answering 400 here where upstream answers 200 with nothing: `PersonsController` hands the id to the people query and never resolves it, alone among the by-name listings. I had over-applied #48's refusal. Fixed separately, with a test.
Sign in to join this conversation.
No description provided.