The Discover tab that got permanently stuck digging
Got a bug report with a screenshot: the Discover tab was frozen on “Digging for deep cuts / Checking your library artists for releases you don’t own yet,” with a “Keep digging” link that didn’t do anything, no matter how many times it was tapped. This one turned into a two-layer bug, and the second layer only showed up because a regression test caught it before I shipped anything.
Problem
Discover works through a library incrementally - check a batch of artists, cache what’s new, remember when each artist was last checked, and only re-check it once it’s stale. The tab shows “Digging for deep cuts” while any artist is still unchecked, and switches to either a feed of results or an “all caught up” empty state once everything’s been checked at least once.
“Stuck forever, retrying doesn’t help” is a very specific shape of bug. It usually means something that’s supposed to change between attempts isn’t actually changing.
Why this approach
I traced the actual code path instead of guessing at MusicKit flakiness. The mechanism that decides “have we checked everything” only updates when an artist’s catalog fetch succeeds. A failed fetch just increments a counter and moves on - the artist is left completely absent from the cache, which means the “have I checked this artist” lookup treats it as “never checked, oldest, must-check-first.” Every single refresh re-selects it, it fails again (for whatever reason it failed the first time), and the “are we fully covered” check can never reach 100% if even one artist can never successfully complete a fetch. That’s exactly “stuck no matter how many times you tap.”
The likely real-world trigger: an artist in someone’s library that MusicKit can’t cleanly resolve to a catalog artist - a self-uploaded or iTunes-matched artist, something outside the neat cases the mock test fixtures cover. That failure mode simply doesn’t exist in a small, hand-built test library, so nothing caught it before a real device with a real (larger, messier) library did.
Implementation
The fix: a failed fetch should still count as “checked,” just without any new results - reusing the same 7-day staleness window the app already has as the natural “try again later” mechanism, instead of inventing a new retry-count or backoff concept. A chronically-bad artist rotates out of “always first” and gets revisited automatically down the line, exactly like any other artist that’s just gone stale.
I wrote the fix, ran the tests, and one of my new tests failed. Good - that’s exactly what a new regression test is for. Turned out there was a second, pre-existing guard: “if every artist in a batch failed, treat the whole thing as catastrophic and don’t cache anything.” That guard is legitimate for a real cold start where the entire pipeline is broken (network down, auth revoked) - you don’t want to silently cache “nothing” and call it done. But once most of the library has already succeeded, the rotation naturally narrows down to just the remaining problem artists. Eventually a batch consists entirely of the one bad artist, which is then 100% of that batch’s failures, which trips the same “catastrophic” guard - and throws before my fix’s cache update even runs.
The actual fix needed both pieces: mark failures as checked, AND make the catastrophic-failure guard only fire when there’s been zero prior successful coverage (a genuine broken-pipeline cold start), not just “this particular small batch happened to fail completely.”
Gotchas
This is the kind of bug that’s basically invisible from a single-round test. “One artist fails, others succeed, coverage moves forward” passes fine on the first check. The break only shows up on the second round, once the batch shrinks down to exactly the leftover problem artist - a scenario none of the existing tests constructed, because they were written to prove the feature works, not to prove it survives a persistently-bad item across multiple rotations. I wrote a new test that specifically exercises “the same artist fails on every single refresh, across multiple calls” - that’s what actually caught the second guard.
Results
Built, installed, and launched the fix on a physical device myself (via devicectl, not simulator - MusicKit doesn’t work there at all) and confirmed Discover now shows real releases instead of staying stuck. Full suite: 165/165, including the two new tests that specifically exercise a chronically-failing artist across multiple rounds.
Bonus finding from the same device pass, unrelated to this bug: tapping a Discover release card does nothing at all. Checked the code - the card’s own doc comment literally says the add-to-playlist action was supposed to ship alongside the “Not Interested” swipe action, and only half of that ever shipped. Filed separately rather than folding it into this fix, since it’s a real feature gap with its own design questions, not a one-line bug.
Related reading
The mirrored window lied about the phone being unlocked
A one-line grouping fix that was already written, and three walls between it and proof: actor isolation, log stream's Mac-only scope, and a mirrored session that looks unlocked when the device isn't.
Pre-release albums, and the fix I couldn't fully verify
Apple's 'Track N' placeholders rendered as real data. The one detection signal I couldn't confirm became the one signal I stopped depending on.
A subscribe button, a MusicKit API I'd never used, and a sheet that dismisses into silence
musicSubscriptionOffer presents Apple's native sheet - and nothing in the app would ever notice it closing. The correctly-coded action that was still a functional dead end.