An album artist upstream does not resolve is still named #71

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

An album artist upstream does not resolve is still named here.

/Items?Recursive=true — 125 items, all of one album and its tracks:

AlbumArtists / ArtistItems
upstream []
ours [{"Id":"15beaa1f…","Name":"MØL"}]

Upstream resolves an album artist name to a MusicArtist row and sends the pair
only where one answers; a name it cannot resolve is dropped rather than sent with
an id. The name here is MØL, whose folder is spelled M├ШL on disk — the same
row #59 named as a sort-name outlier, and one of the two artist rows that fold
together.

So this is the resolution failing to match, not the field being wrong: we find a
row upstream does not.

The last of the differences in that listing, alongside #72, #73 and #74.

An album artist upstream does not resolve is still named here. `/Items?Recursive=true` — 125 items, all of one album and its tracks: | | `AlbumArtists` / `ArtistItems` | |---|---| | upstream | `[]` | | ours | `[{"Id":"15beaa1f…","Name":"MØL"}]` | Upstream resolves an album artist name to a `MusicArtist` row and sends the pair only where one answers; a name it cannot resolve is dropped rather than sent with an id. The name here is `MØL`, whose folder is spelled `M├ШL` on disk — the same row #59 named as a sort-name outlier, and one of the two artist rows that fold together. So this is the resolution failing to match, not the field being wrong: we find a row upstream does not. The last of the differences in that listing, alongside #72, #73 and #74.
Author
Collaborator

Fixed. Upstream lowercases the name twice, differently, and that asymmetry
is the whole bug.

LinkedChildrenService.FindArtists (LinkedChildrenService.cs:63):

var lowerNames = artistNames.Select(n => n.ToLowerInvariant()).ToArray();
… .Where(e => lowerNames.Contains(e.Name!.ToLower()))

ToLowerInvariant() runs in C# over every script; e.Name.ToLower() is
translated to SQLite's lower(), which touches ASCII only. So a stored name
carrying an uppercase letter outside ASCII is reachable by nothing. And the
match is on the spelled Name, not on the folded CleanName this port joined
on. A name that reaches no row is dropped rather than sent with an id.

All 125 items were that, in three groups:

stored rows folded alike upstream ours
Fall Out Boy / Fall Out Boy fall out boy the exact row the trailing-space row (98)
Scooter & Harris & Ford / Scooter, Harris & Ford scooter harris ford the exact row the comma row (2)
MØL ×2 mol [] — lower('MØL') is mØl an id (25)

Of 201 distinct referenced artist names in the library, exactly one is
unresolvable under upstream's rule, so it does not over-reach.

GenreItems and Studios keep the old derivation: upstream computes those ids
from the name rather than looking a row up.

A page's names are resolved in one query, so there is no per-item lookup.

field before after
AlbumArtists 125 0
ArtistItems 125 0
Fixed. Upstream lowercases the name **twice, differently**, and that asymmetry is the whole bug. `LinkedChildrenService.FindArtists` (`LinkedChildrenService.cs:63`): var lowerNames = artistNames.Select(n => n.ToLowerInvariant()).ToArray(); … .Where(e => lowerNames.Contains(e.Name!.ToLower())) `ToLowerInvariant()` runs in C# over every script; `e.Name.ToLower()` is translated to SQLite's `lower()`, which touches **ASCII only**. So a stored name carrying an uppercase letter outside ASCII is reachable by nothing. And the match is on the spelled `Name`, not on the folded `CleanName` this port joined on. A name that reaches no row is dropped rather than sent with an id. All 125 items were that, in three groups: | stored rows | folded alike | upstream | ours | |---|---|---|---| | `Fall Out Boy` / `Fall Out Boy ` | `fall out boy` | the exact row | the trailing-space row (98) | | `Scooter & Harris & Ford` / `Scooter, Harris & Ford` | `scooter harris ford` | the exact row | the comma row (2) | | `MØL` ×2 | `mol` | `[]` — `lower('MØL')` is `mØl` | an id (25) | Of 201 distinct referenced artist names in the library, exactly one is unresolvable under upstream's rule, so it does not over-reach. `GenreItems` and `Studios` keep the old derivation: upstream computes those ids from the name rather than looking a row up. A page's names are resolved in one query, so there is no per-item lookup. | field | before | after | |---|---|---| | `AlbumArtists` | 125 | **0** | | `ArtistItems` | 125 | **0** |
Sign in to join this conversation.
No description provided.