Skip to content

Apple Music album art missing when MB release title doesn't match Apple Music album #175

@dprodger

Description

@dprodger

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_links0 rows (no album-level Apple Music link)
  • release_imagery0 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_links1 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 urlTemplateartwork 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';

Metadata

Metadata

Assignees

No one assigned

    Labels

    data-cleanupprojected related to the underlying metadata, scrapers, ingesters, etc.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions