Skip to content

Instantly share code, notes, and snippets.

@jubishop
Created February 24, 2026 19:18
Show Gist options
  • Select an option

  • Save jubishop/d9e0f769fa6cb846c77552dd5e23125a to your computer and use it in GitHub Desktop.

Select an option

Save jubishop/d9e0f769fa6cb846c77552dd5e23125a to your computer and use it in GitHub Desktop.

⏺ Summary of All Three Bug Reports

All three reports are from the same user listening over Bluetooth AirPods with episodes played from local cache while the app is backgrounded. Two are related to the same root cause, and one is a distinct bug.


Bug 1 & 3: Audio Repeating (Feb 18 & Feb 21) — !con Error

Both "repeating" reports are manifestations of the known !con error (OSStatus 560164718). The new finding: the audio loops/repeats for ~10-15 seconds before failedToPlayToEndTimeNotification fires. The Core Audio decoder appears to retry the same buffer when it fails, causing the user to hear a few seconds of audio on repeat before AVFoundation surfaces the error.

Feb 18 timeline: Episode playing from cache over Bluetooth, backgrounded for ~5 min → audio starts repeating → !con fires at 7:45:53am → auto-recovery reloads and seeks to 30:35 → plays for ~1.5s then unexpectedly pauses (no logged reason) → user reopens app, presses play, seeks back to hear what they missed.

Feb 21 timeline: Episode playing from cache over Bluetooth, backgrounded for ~2m44s → audio starts repeating → user pauses → 594ms later !con fires → auto-recovery reloads at 1:08:49 → user rapidly toggles play/pause, opens app, sends bug report.

Also found: A fourth unreported !con occurrence on Feb 20 at 7:10am PST with a different episode — same pattern.


Bug 2: Position Reset to Start (Feb 17) — setOnDeck Race Condition

This is a different bug. The user's AirPods auto-paused (ear detection while sleeping), and ~30 seconds later iOS sent a changePlaybackPosition(0.0) command that reset the episode to the beginning.

Root cause: In NowPlayingInfo.setOnDeck(), the Now Playing dictionary is initialized with elapsedPlaybackTime = 0.0 before the actual seek to the saved position occurs. When iOS queries Now Playing info to "restore" after AirPods auto-pause, it can pick up the stale 0.0 value and send a seek-to-zero command.

The fix is straightforward — set the correct elapsed time in setOnDeck:

// In NowPlayingInfo.setOnDeck(): // Instead of: nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = 0.0 nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackProgress] = 0.0

// Use: let elapsed = onDeck.episode.currentTime.safe.seconds let total = onDeck.duration.safe.seconds nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = elapsed nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackProgress] = total > 0 ? elapsed / total : 0.0


Recommended Next Steps

For Bug 2 (position reset): This looks actionable now. Want me to look at NowPlayingInfo.swift and implement the fix?

For Bugs 1 & 3 (!con repeating): The auto-recovery is working but the user experience is poor (10-15s of looping audio). To diagnose further, we could:

  1. Detect stuck positions early — the periodic time observer fires every 250ms; if the position doesn't advance (or goes backward) for N consecutive samples, trigger recovery proactively instead of waiting for the failedToPlayToEndTimeNotification
  2. Log position samples periodically during background playback (even every 30s at debug level) to confirm the looping theory
  3. Log reasonForWaitingToPlay when timeControlStatus changes to .paused — this would explain the mysterious auto-pause after recovery in the Feb 18 case
  4. Save position explicitly at the start of handlePlaybackFailure before clearing the player, to minimize replay on recovery
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment