MusicKit queue reorder crashes RemotePlayerService; MediaPlayer queue.items contains nil

Hey everyone,

I need to reorder a four-song Apple Music application queue while keeping the same selected occurrence, playback time, and playing/paused state. I reproduced two distinct failures in a standalone app without persistence or synchronization. I do not yet know whether these failures have a common cause.

Device: iPhone 16 Pro, iOS 27.0.1 (24A446), built-in audio. Music authorization and catalog subscription checks succeed. Four distinct catalog songs resolve successfully in the Japanese storefront, in the order A, B, C, D. These letters are anonymized labels for the songs used in the measured runs; the actual catalog IDs are omitted from this public post. This does not establish that the issue occurs with every four-song selection. Repeat and shuffle are off.

  1. MusicKit reorder after a stable paused baseline

Install ApplicationMusicPlayer.Queue once, starting at song D. Play once, then pause after several seconds; verify all four entries and unchanged Current/time for over ten seconds. Move the non-Current prefix in one operation:

queue.entries.move(fromOffsets: IndexSet(integersIn: 0..<3), toOffset: 4)

Expected: [A,B,C,D*] becomes [D*,A,B,C], retaining Current and elapsed time. RemotePlayerService instead terminates with SIGABRT during queue modification. The exception stack includes _componentsForContentItemID: and _qfa_performInsertPlaybackContext:atPosition:afterContentItemID:sectionIdentifier:actions:completion:. The client then hangs in synchronous XPC connection establishment on main. This also occurred with all app-initiated post-move SDK reads suppressed; the service report predates the first scheduled read. A direct Current move 3→0 produced a matching service exception stack in a separate run.

  1. MediaPlayer alternative fails before any reorder

Using applicationQueuePlayer instead, set one MPMusicPlayerStoreQueueDescriptor for the same songs A–D with startItemID set to song D's actual catalog ID. Set repeat/shuffle off, activate an AVAudioSession playback/default session and call play once. Immediately call performQueueTransaction:completionHandler: with an empty transaction block. Completion is on main and error is nil. All queue access is synchronous inside that callback. The relevant Objective-C read order is:

id raw = queue.items;
NSUInteger currentIndex = player.indexOfNowPlayingItem;
id current = player.nowPlayingItem;
NSArray *items = raw; // raw was checked to be a nonnil NSArray
NSUInteger count = items.count;
for (NSUInteger i = 0; i < count; ++i) {
    id item = [items objectAtIndex:i];
    if (!item) { /* record index and end observation */ break; }
    // Validate MPMediaItem and copy its nonempty playbackStoreID.
}

count was 4, currentIndex was 2, current was nonnil, and elements 0 and 1 validated. objectAtIndex:2 returned nil. No queue object escapes the callback. The guard ended the read with audio continuing and UI responsive. An earlier Swift queue.items.map observation crashed in Swift element dynamic casting. This newer result does not establish which song occupies returned index 2. There was no queue mutation or repeat read in this MediaPlayer trial.

Both startup sequences logged "ping did not pong"; the MusicKit reorder trial subsequently reached the stable paused baseline. I cannot rule out startup's contribution. I have not established the behavior on another device/OS.

Questions

  • Is modifying entries the supported way to reorder the full application queue across Current while retaining its occurrence and continuous audio?
  • For MediaPlayer, is a successful read-only transaction completion expected to provide a fully readable nonnull items array? Is there a documented readiness condition before enumeration that this sequence is missing?
  • If MediaPlayer transactions are a suitable alternative, how should callers target duplicate occurrences (not just song IDs) for removal/insertion?

I can provide a minimal project and the two separate failure reports through Feedback Assistant. Which component and additional diagnostics would be most useful? No Feedback ID exists yet.

Update: a successful OFF control and a failing Current-crossing reorder

I narrowed down the MusicKit issue with two standalone diagnostic runs on an iPhone 16 Pro, iOS 27.0.1 (24A446), using built-in audio. Both use ApplicationMusicPlayer, Repeat OFF, Shuffle OFF, and the same four distinct Apple Music catalog songs A–D. These are anonymized labels for the tested songs; I have not established that arbitrary songs behave identically.

The goal remains to reorder the queue while preserving the selected occurrence, playback position, and playing/paused state, including uninterrupted audio when playing. The new comparison below concerns PLAYING A.

Both runs use the same startup: install only A, play once, observe it, append B/C/D, explicitly keep Repeat OFF, then verify ABCD with A current and advancing time. The diagnostic has no Room synchronization, persistence, repair, replay, or seek recovery.

Success: [A]-B-C-D -> [A]-D-B-C Failure: [A]-B-C-D -> D-[A]-B-C

In both cases the app takes a mutable copy of queue.entries, removes D at index 3, inserts that same retained Entry, and assigns queue.entries once. The only mutation-plan difference is D's insertion index: 1 for ADBC versus 0 for DABC. A is never removed or reinserted in the local copy; no currentEntry setter is used.

ADBC retained A, order, and advancing playback time through the approximately 10-second observation; audio and scrolling remained normal. Non-current SDK IDs changed, so this is not a claim of durable identity for every entry.

DABC initially returned the expected four entries, the original A at index 1, and playing time 13.746/13.747 seconds in two immediate samples. Playback then stopped and the UI became unresponsive. No marker for the next scheduled 0.3-second sample appeared. Xcode Console reported an XPC service interruption. After Debug Pause, the client main thread was waiting synchronously for XPC inside MediaPlayer _establishConnectionIfNeeded / onServerAsync, through a dispatched main-queue block.

The associated RemotePlayerService report at 2026-10-01 20:43:34 +0900 shows EXC_CRASH/SIGABRT and an assertion path:

performQueueModifications:completion: -> performInsertCommand:targetContentItemID:completion: -> _qfa_performInsertPlaybackContext:atPosition:afterContentItemID:sectionIdentifier:actions:completion: -> _componentsForContentItemID: -> NSAssertionHandler / abort

This framework exception path also appears in the earlier reports. The assertion message/arguments are absent. Both new runs logged "ping did not pong" during initial Play, then passed startup checks. They were separate runs; changing the destination also changes A's index and neighbors. I cannot attribute the cause solely to the numeric index. ALL with this same native DABC/A0->A1 operation has not been tested.

Is this retained-Entry copy/assignment a supported way to reorder across the active entry without interrupting playback? If so, is there a known issue or fix for this assertion? Otherwise, what public operation and acknowledgement should be used to preserve the selected occurrence, time, and transport state while changing the full linear order?

Filed as FB25016605, with the RemotePlayerService crash report and the successful/failed comparison logs attached.

MusicKit queue reorder crashes RemotePlayerService; MediaPlayer queue.items contains nil
 
 
Q