From 22cd17d0648e2ab0154305e8fb6c82c4e7781551 Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 2 Nov 2026 02:56:03 -0800 Subject: [PATCH 1/3] docs(jellyfin): the door that scans is /Library/Refresh, and the art door names its field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The page sent the next agent to POST /Items/{id}/Refresh?Recursive=true per library to make a new folder visible. Measured against a Shows library that had never been identified: that route answers 204 and queues nothing — item census byte-identical, ScheduledTasks idle, journal silent, and still a silent 204 after a service restart. The door that works is POST /Library/Refresh, and the progress read is ScheduledTasks -> Scan Media Library -> CurrentProgressPercentage. RefreshStatus on the VirtualFolders record stays Idle through a real scan, so it is not a progress read at all; a 204 cannot distinguish accepted-and-discarded from accepted-and-queued, so the acceptance read is the journal naming folders. Also recorded the art door's wire shape, because guessing it reads as a server bug: the list response carries the address in Url (there is no ImageUrl), the Download POST takes camelCase type/imageUrl and answers 204, and PascalCase or an empty imageUrl answers 500. RemoteImages is empty for items with no ProviderIds, so art coverage is capped by identification, not by the image door. --- serverAppConfigs-docs/Dankserver/Jellyfin.md | 35 ++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/serverAppConfigs-docs/Dankserver/Jellyfin.md b/serverAppConfigs-docs/Dankserver/Jellyfin.md index 9d11766..2c4298c 100644 --- a/serverAppConfigs-docs/Dankserver/Jellyfin.md +++ b/serverAppConfigs-docs/Dankserver/Jellyfin.md @@ -119,6 +119,17 @@ store on a build where the automatic image pass will not run at all — it is ho the Movies library got its art: 2,515 of 2,564 films carry a primary now, and the rest have none in TMDb (shorts like `Astartes`, files whose names match nothing). +**The Download door's exact wire shape:** the list response carries the address in +`Url` — there is no `ImageUrl` field — and the POST takes camelCase query params, +`?type=Primary&imageUrl=`, answering `204`; the stored tag then appears in +`ImageTags`. PascalCase params, or an `imageUrl` left empty, answer `500`, which +reads as a server fault and is a field-name fault. + +**`RemoteImages` answers empty for an item with no `ProviderIds`** — no provider id, +nothing to look up. Art coverage is capped by identification, not by the image door: +the items a campaign returns nothing for are the unidentified ones, and no image +retry will change that. + **API shape on 12.x:** `/Items` and `/Items/{id}` need `UserId` when authenticated by API key — without it the answer is `400 Error processing request`, which reads exactly like an authentication failure. `MetadataRefreshMode` @@ -284,12 +295,24 @@ anything. The fix is `systemctl --user restart jellyfin.service`, one POST after health answers, and then believe `ScheduledTasks` State at 130 % CPU, not the response code. -**A scan that must see a new folder has to be recursive.** `POST /Library/Refresh` -is the incremental pass, and inotify does not cross a rootless podman bind, so -folders created on the host stay invisible to it. The move is -`POST /Items/{id}/Refresh?Recursive=true` (204) per library, the id from -`GET /Library/VirtualFolders` — its field is `ItemId`, not `Id` — and that same -record's `RefreshStatus` is the progress read. +**The door that scans is `POST /Library/Refresh` (204), and `ScheduledTasks` is the +progress read.** Measured 2026-11-02 against a `Shows` library that had never been +identified: the per-library `POST /Items/{id}/Refresh?Recursive=true` answers `204` +and queues **nothing** — item census identical afterwards, `Scan Media Library` +idle, journal silent — and it is still an empty `204` after a service restart, so +that status code carries no information at all. `/Library/Refresh` walks every +library; within seconds the journal names folders (`…/TVShows/…`, +`EpisodeMetadataService`) and `GET /ScheduledTasks` reports +`Scan Media Library | Running | 75 %` while the process sits near 200 % CPU. + +**`RefreshStatus` on the `GET /Library/VirtualFolders` record is not a progress +read.** It stayed `Idle` through a scan that was verifiably running at 75 %. The +record's useful field is `ItemId`, and the live library set is still the entries +whose `Locations` are non-empty. + +`inotify` does not cross a rootless podman bind, so folders created on the host +stay invisible until a pass like this runs; every pass that writes into a library +ends by firing one. **`Movies` has no watcher at all.** `EnableRealtimeMonitor` is per library (table in *Data layout*) and it is false for `Movies` and `Collections`. Nothing notices a -- 2.54.0 From f1ae1ddb36e75c84646496a1f6b330e2afb55af6 Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 2 Nov 2026 02:57:25 -0800 Subject: [PATCH 2/3] docs(audiobookshelf): the scanner refusal names the file, not the bind The first full scan logged "Invalid data found when processing input" per file and carried on. That line is about the file: the scanner skips it, so the book never appears in the library at all. Census of the 43 refused files: 38 were 0 bytes, 3 held WAV bytes behind a .mp3 name, 2 were unreadable. The check to run first is a byte count, not a server investigation. Full suite: 818 tests, exit 0. --- serverAppConfigs-docs/Dankserver/Audiobookshelf.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/serverAppConfigs-docs/Dankserver/Audiobookshelf.md b/serverAppConfigs-docs/Dankserver/Audiobookshelf.md index e079d20..f490b24 100644 --- a/serverAppConfigs-docs/Dankserver/Audiobookshelf.md +++ b/serverAppConfigs-docs/Dankserver/Audiobookshelf.md @@ -124,6 +124,12 @@ the file, not the bind: the same line count grows while the total climbs. cross a rootless podman bind — measured for [[Jellyfin]], whose page owns that law — so the in-container watcher sees nothing a host process files onto the array, and the deployer's re-run of the bootstrapper is the cheap scan trigger. +- **`Invalid data found when processing input` names the file, not the bind.** The + scanner logs it per file and skips the file — the book never appears — so a + missing title beside those lines is library debris, not a server fault. Census of + the refusals on the first full scan: 38 of 43 files were 0 bytes, 3 were WAV + bytes wearing a `.mp3` name, 2 were unreadable. `stat -c %s` before any + investigation of the server. ## Verification -- 2.54.0 From 93725f42b375e2a587f59b943084a9ad14548f6b Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 2 Nov 2026 15:03:48 -0800 Subject: [PATCH 3/3] docs(jellyfin): correct the posture table and three API/art laws - the per-library switches are under LibraryOptions, not top-level DTO keys - Shows was flipped on 2026-11-02; Music is the only silent file index left - never pin Providers= on a TV art loop: the TVDB-only offers disappear - /Items?Ids= needs no UserId where /Items/{id} does, so verify writes there --- serverAppConfigs-docs/Dankserver/Jellyfin.md | 36 +++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/serverAppConfigs-docs/Dankserver/Jellyfin.md b/serverAppConfigs-docs/Dankserver/Jellyfin.md index 2c4298c..202be6f 100644 --- a/serverAppConfigs-docs/Dankserver/Jellyfin.md +++ b/serverAppConfigs-docs/Dankserver/Jellyfin.md @@ -81,21 +81,25 @@ so an empty `` switches art off while `ImageFetcherOrder` stays fully populated — order is not enablement — and the populated `` built next to it makes the library look healthy. -**Live posture, measured 2026-11-02** from `GET /Library/VirtualFolders`. The DTO is -PascalCase — `Name`, `CollectionType`, `Locations`, `ItemId`, `RefreshStatus` — and a -census written against the 10.x camelCase keys reads `None` for everything, which -looks exactly like an unconfigured library. +**Live posture, measured 2026-11-02** from `GET /Library/VirtualFolders`, cross-checked +against each library's `config/root/default//options.xml`. The per-library switches +are NOT top-level DTO keys: the folder carries `Name`, `CollectionType`, `Locations`, +`ItemId`, `PrimaryImageItemId`, `RefreshStatus` and `LibraryOptions`, and the switches live +inside `LibraryOptions`. Reading `EnableInternetProviders` off the folder itself returns +`None` for every library, which looks exactly like an unconfigured library — that is the +10.x camelCase trap one level deeper. | Library | `CollectionType` | `EnableInternetProviders` | `EnableRealtimeMonitor` | |---|---|---|---| | `Movies` | movies | true (fixed 2026-11-02) | **false** | -| `Shows` | tvshows | **false** | true | +| `Shows` | tvshows | true (flipped 2026-11-02, before the TV arm ran) | true | | `Music` | music | **false** | true | -| `Collections` | boxsets | **false** | false | +| `Collections` | boxsets | no element — false by default | false | -`Shows` and `Music` are silent file indexes in the sense above: a refresh answers -`204`, stores nothing, logs nothing. Any metadata or artwork work on either one -starts by flipping the switch, never by firing a scan. +`Music` is still a silent file index in the sense above: a refresh answers `204`, stores +nothing, logs nothing, and any metadata or artwork work on it starts by flipping the switch, +never by firing a scan. `Shows` was flipped on 2026-11-02 and the flip is at rest in the +server's own `options.xml`: scan #7 resolved provider ids for 731 of 733 series. **The per-library option door on 12.x is `POST /Library/VirtualFolders/LibraryOptions`** — `GET` there answers `405`, which is how the route announces itself. The 10.x doors @@ -130,9 +134,17 @@ nothing to look up. Art coverage is capped by identification, not by the image d the items a campaign returns nothing for are the unidentified ones, and no image retry will change that. -**API shape on 12.x:** `/Items` and `/Items/{id}` need `UserId` when -authenticated by API key — without it the answer is `400 Error processing -request`, which reads exactly like an authentication failure. `MetadataRefreshMode` +**Never pin `Providers=` on a TV art loop.** The pinned form reports `none` for exactly the +items the unpinned `RemoteImages` query answers for: the TVShows arm's 16 fillable seasons +all offered `TheTVDB` posters, and a `Providers=TheMovieDb` pass — correct for movies, wrong +here — logged `none` for every one of them and called the gap closed. The unpinned answer is +the provider census; the pinned one only proves one provider is empty. + +**API shape on 12.x:** `/Items/{id}` needs `UserId` when authenticated by API key — without +it the answer is `400 Error processing request`, which reads exactly like an authentication +failure, and it is easy to hit as a *verification* read right after a write that succeeded. +The `/Items` list route, `?Ids=` included, does not need it, so verify a write through +the list route. `MetadataRefreshMode` accepts `Default` (and `Realtime`) only; `Full` and `ValidationFailure` are rejected outright, and what forces the providers to re-run is `ReplaceAllMetadata=true`. -- 2.54.0