Symptom
Recording 3b3b8f85-3b33-4bbc-a8ce-95188ed6dc8c ("By the River Sainte Marie", Johnny Mercer With Paul Weston and His Orchestra, on MB release "Sweet Georgia Brown" 1995) shows as playable on Apple Music in the iOS/Mac app but has no album art. The same recording on Apple Music clearly has art ("By the River Sainte Marie" album, 2014).
A --force-refresh --rematch against the new Apple Music Feed catalog did not fix it.
What's in the DB
For release 1ec447b1-b8ab-4514-95d6-046f618cf582:
release_streaming_links — 0 rows (no album-level Apple Music link)
release_imagery — 0 rows (so no album art)
releases.cover_art_url — null (no Cover Art Archive imagery either)
releases.apple_music_searched_at — set to today by the rematch
recording_release_streaming_links — 1 row for apple_music, service_id=323034612, match_method=fuzzy_search, matched_at=2025-12-24
The track-level row is what makes the recording look "playable"; album art is keyed off release_imagery / releases.cover_art_url, which are both empty.
Root cause
The album-level search in backend/integrations/apple_music/search.py searches the catalog by the release's title + artist:
- Search input:
"Sweet Georgia Brown" / "Johnny Mercer With Paul Weston and His Orchestra" / 1995
- Reality on Apple Music:
"By the River Sainte Marie" / "Johnny Mercer" / 2014 (collectionId=864085215)
The MB release is essentially a 78 RPM single where MusicBrainz used the B-side ("Sweet Georgia Brown") as the release title; the only track on the release is "By the River Sainte Marie". None of the search-ladder strategies in search.py:59-93 (strip ensemble, strip live, primary artist, album-only, punctuation-stripped, main-title-only) ever generate the query "By the River Sainte Marie", so every candidate gets rejected by validate_album_match on album-name similarity (matching.py:91-96).
With the worker's local_catalog_only=True (research_worker/handlers/apple.py:53) there's no iTunes API fallback either. The matcher just calls mark_release_searched and exits (matcher.py:303-308). No album link → _match_track_on_release is never called → no artwork fetch.
This is likely a long tail: any single-track MB release where MB titled the release after a different track than the one we care about will exhibit the same problem.
Stale track ID (related, smaller issue)
service_id=323034612 is a dead Apple Music track ID:
https://music.apple.com/us/song/323034612 → 404
https://itunes.apple.com/lookup?id=323034612 → 0 results
The current track ID for the same content is 864085280 (on album 864085215). The Dec 2025 match predates whatever ID rotation happened. We're showing a green "playable" indicator that points at a dead URL.
Separate latent bug found while investigating
In backend/integrations/apple_music/search.py:211 (_convert_catalog_album):
artwork_url = catalog_data.get('artworkUrl')
But the catalog query in feed.py:738 returns url_template AS urlTemplate, and the index-build SELECT in catalog_index.py:264 writes the column as url_template. So artworkUrl is never set, and _convert_catalog_album always returns an album with no artwork. Every successful local-catalog album match then pays an iTunes API round-trip in matcher.py:319-327 to fetch artwork that's already in the catalog. Not the cause of the missing-art issue above, but worth fixing while we're in this code.
Possible fixes (need to decide)
A. Song-level fallback in the matcher. When album-level search returns nothing, call catalog.search_songs(artist_name=<release_artist>, song_title=<our_song>). Each result carries albumId / albumName — pick the best with validate_album_match on the catalog album, then save the album link, fetch artwork, and run _match_track_on_release as today. Recovers this case (Apple's song catalog has "Sweet Georgia Brown" / Johnny Mercer / albumId=864085215) and likely the broader long tail.
B. Use the existing track ID as a back-door to the album. When a track-level link already exists but no album link, lookup_track(track_id) returns album_id + artwork, so we could backfill. Doesn't help here because the cached track ID is dead, but might help other rows.
C. Lower the album-name similarity threshold or add a "single-track release with track-title-mismatched-from-release-title" search strategy. Riskier — could increase false positives elsewhere.
D. Fix the urlTemplate → artwork field-name mismatch in _convert_catalog_album. Independent of the album-match question, just removes the unnecessary iTunes API call when local-catalog matches succeed.
Repro
SELECT rel.id, rel.title, rel.artist_credit, rel.release_year,
(SELECT COUNT(*) FROM release_streaming_links WHERE release_id=rel.id AND service='apple_music') AS apple_album_rows,
(SELECT COUNT(*) FROM release_imagery WHERE release_id=rel.id) AS imagery_rows,
rrsl.service_id AS apple_track_id, rrsl.matched_at
FROM releases rel
JOIN recording_releases rr ON rr.release_id = rel.id
LEFT JOIN recording_release_streaming_links rrsl
ON rrsl.recording_release_id = rr.id AND rrsl.service='apple_music'
WHERE rr.recording_id = '3b3b8f85-3b33-4bbc-a8ce-95188ed6dc8c';
Symptom
Recording
3b3b8f85-3b33-4bbc-a8ce-95188ed6dc8c("By the River Sainte Marie", Johnny Mercer With Paul Weston and His Orchestra, on MB release "Sweet Georgia Brown" 1995) shows as playable on Apple Music in the iOS/Mac app but has no album art. The same recording on Apple Music clearly has art ("By the River Sainte Marie" album, 2014).A
--force-refresh --rematchagainst the new Apple Music Feed catalog did not fix it.What's in the DB
For release
1ec447b1-b8ab-4514-95d6-046f618cf582:release_streaming_links— 0 rows (no album-level Apple Music link)release_imagery— 0 rows (so no album art)releases.cover_art_url— null (no Cover Art Archive imagery either)releases.apple_music_searched_at— set to today by the rematchrecording_release_streaming_links— 1 row forapple_music,service_id=323034612,match_method=fuzzy_search,matched_at=2025-12-24The track-level row is what makes the recording look "playable"; album art is keyed off
release_imagery/releases.cover_art_url, which are both empty.Root cause
The album-level search in
backend/integrations/apple_music/search.pysearches the catalog by the release's title + artist:"Sweet Georgia Brown"/"Johnny Mercer With Paul Weston and His Orchestra"/ 1995"By the River Sainte Marie"/"Johnny Mercer"/ 2014 (collectionId=864085215)The MB release is essentially a 78 RPM single where MusicBrainz used the B-side ("Sweet Georgia Brown") as the release title; the only track on the release is "By the River Sainte Marie". None of the search-ladder strategies in
search.py:59-93(strip ensemble, strip live, primary artist, album-only, punctuation-stripped, main-title-only) ever generate the query "By the River Sainte Marie", so every candidate gets rejected byvalidate_album_matchon album-name similarity (matching.py:91-96).With the worker's
local_catalog_only=True(research_worker/handlers/apple.py:53) there's no iTunes API fallback either. The matcher just callsmark_release_searchedand exits (matcher.py:303-308). No album link →_match_track_on_releaseis never called → no artwork fetch.This is likely a long tail: any single-track MB release where MB titled the release after a different track than the one we care about will exhibit the same problem.
Stale track ID (related, smaller issue)
service_id=323034612is a dead Apple Music track ID:https://music.apple.com/us/song/323034612→ 404https://itunes.apple.com/lookup?id=323034612→ 0 resultsThe current track ID for the same content is
864085280(on album864085215). The Dec 2025 match predates whatever ID rotation happened. We're showing a green "playable" indicator that points at a dead URL.Separate latent bug found while investigating
In
backend/integrations/apple_music/search.py:211(_convert_catalog_album):But the catalog query in
feed.py:738returnsurl_template AS urlTemplate, and the index-build SELECT incatalog_index.py:264writes the column asurl_template. SoartworkUrlis never set, and_convert_catalog_albumalways returns an album with no artwork. Every successful local-catalog album match then pays an iTunes API round-trip inmatcher.py:319-327to fetch artwork that's already in the catalog. Not the cause of the missing-art issue above, but worth fixing while we're in this code.Possible fixes (need to decide)
A. Song-level fallback in the matcher. When album-level search returns nothing, call
catalog.search_songs(artist_name=<release_artist>, song_title=<our_song>). Each result carriesalbumId/albumName— pick the best withvalidate_album_matchon the catalog album, then save the album link, fetch artwork, and run_match_track_on_releaseas today. Recovers this case (Apple's song catalog has "Sweet Georgia Brown" / Johnny Mercer /albumId=864085215) and likely the broader long tail.B. Use the existing track ID as a back-door to the album. When a track-level link already exists but no album link,
lookup_track(track_id)returnsalbum_id+ artwork, so we could backfill. Doesn't help here because the cached track ID is dead, but might help other rows.C. Lower the album-name similarity threshold or add a "single-track release with track-title-mismatched-from-release-title" search strategy. Riskier — could increase false positives elsewhere.
D. Fix the
urlTemplate→artworkfield-name mismatch in_convert_catalog_album. Independent of the album-match question, just removes the unnecessary iTunes API call when local-catalog matches succeed.Repro