Fixing a Tricky Playback Issue in My Flutter Music App

BackerLeader posted 2 min read

I recently ran into a subtle but super frustrating issue in my Flutter music player app using just_audio and audio_service. It had to do with updating the playback queue when selecting a new song — and I want to share how I fixed it.

The Problem

Let’s say I have 5 songs:

a  b  c  d  e

Here's what was happening:

I open the app and click on song b.

Music starts playing . I can see the notification with controls.

I click next in the notification → it moves to c. Perfect!

I go back to the app and tap on song a.

Now... song plays but playback control like next and previous don't work.

So clearly, something went wrong when I tried to load a new playlist and song from the UI.

My (Buggy) Code

This is how I was updating the queue in my AudioHandler:

Future<void> updateQueue(List<MediaItem> newQueue) async {
  await _player.stop();              // Stop current audio
  _playlist.clear();                 //  Clear existing playlist

  final audioSources = newQueue.map((item) {
    final uri = item.extras?['uri'] as String;
    return AudioSource.uri(Uri.parse(uri));
  }).toList();

  _playlist.addAll(audioSources);   //  Add new items to old list
  await _player.setAudioSource(_playlist); //  Reuse the same playlist

  queue.add(newQueue);              //  Update the queue
}

The Hidden Issue

I was clearing and modifying the same _playlist instance that was already connected to the player.

just_audio doesn't always like it when you mutate a ConcatenatingAudioSource after it's been set — especially if it's already active in playback.

That caused inconsistent behavior.

The Fix: Use a Fresh Playlist Instance

Instead of modifying the existing _playlist, I now create a brand new ConcatenatingAudioSource every time I update the queue:

@override
Future<void> updateQueue(List<MediaItem> newQueue) async {
  await _player.stop(); // Stop safely

  final newAudioSources = newQueue.map((item) {
    final uri = item.extras?['uri'] as String;
    return AudioSource.uri(Uri.parse(uri));
  }).toList();

  final newPlaylist = ConcatenatingAudioSource(children: newAudioSources); // Fresh playlist

  await _player.setAudioSource(newPlaylist); // Clean set

  _playlist.clear();         // Optional: if you track items
  _playlist.addAll(newAudioSources);

  queue.add(newQueue);       // Update queue after setting source
}

When working with just_audio and audio_service, always pass a new AudioSource instance when switching playlists or queues.
Avoid mutating an existing one after it’s been assigned to the player. Otherwise, you'll run into strange bugs like:

Next/Previous buttons breaking
Playback getting stuck
Notifications going out of sync

If you read this far, tweet to the author to show them you care. Tweet a Thanks

I find this super interesting, how simple changes can fix a lot. Great tip.

Yeah, I was expecting I need to do more changes but fix was small. It is indeed very interesting Ricardo.

More Posts

How I Paid Off a Little Technical Debt in My Flutter Music App

rahul mishra - Aug 15

When to Use setState, Provider, and Consumer in Flutter

rahul mishra - Aug 11

After facing weird permission issues, I built my own music app in 6 hours.

rahul mishra - Jul 14

Why does my Flutter music player jump from 0:00 to actual time? (One-liner fix inside!)

rahul mishra - Aug 8

Why I Started Creating Models in My Flutter Project

rahul mishra - Aug 20
chevron_left