Bluetooth Speaker Won't Pair on Linux: 3 Real Fixes
Bluetooth pairing fails on Linux mostly due to PulseAudio or module-bluetooth-discover not loading. Here's what actually fixes it.
1. PulseAudio's bluetooth module isn't loaded
This is the #1 reason Bluetooth speakers fail on Linux. People blame BlueZ or the speaker, but what's actually happening here is that PulseAudio drops the audio profile the second the speaker connects.
You pair it with bluetoothctl, it shows as connected, but no sound comes out. Or the speaker disappears after 5 seconds.
The fix: Load the module-bluetooth-discover module in PulseAudio.
pactl load-module module-bluetooth-discover
That loads it for this session only. To make it permanent:
sudo nano /etc/pulse/default.pa
Find the line that says #!load-module module-bluetooth-discover and remove the # so it reads load-module module-bluetooth-discover. Save, exit, then run:
pulseaudio -k && pulseaudio --start
Now try pairing again. The reason this works is that PulseAudio needs to see the bluetooth adapter as an audio sink, not just a generic bluetooth device. Without this module, PulseAudio ignores the speaker entirely.
Real-world trigger: Fresh Ubuntu 22.04 install, or after a distro upgrade from 20.04 to 22.04. The module got removed during the upgrade.
2. The wrong audio profile is selected
Even with the module loaded, the speaker might connect but stay on the HFP (Headset Profile) or HSP (Hands-Free Profile) instead of A2DP (Advanced Audio Distribution Profile). HFP is for phone calls — mono, low quality, often silent for music.
Check the profile with:
pactl list cards | grep -E 'Name:|Active Profile:'
You'll see something like active profile: headset_head_unit. That's your problem.
Switch it to A2DP:
pactl set-card-profile bluez_card.XX_XX_XX_XX_XX_XX a2dp_sink
Replace XX_XX_XX_XX_XX_XX with your speaker's MAC address (lowercase, colons). You can get the exact card name from the list cards output.
If the profile switch fails, you might need to install pulseaudio-modules-bt (on Debian/Ubuntu) or pulseaudio-modules-bt-git (from AUR on Arch). The reason these packages exist is that the stock PulseAudio bluetooth support is intentionally limited — they made A2DP optional to reduce dependencies.
3. BlueZ is missing the bluetooth audio plugin
Less common but happens on minimal or server installs. BlueZ itself needs the bluetooth audio plugin (/usr/lib/bluetooth/plugins/audio.so). If it's missing, no audio codec negotiation happens.
Check if the plugin exists:
ls /usr/lib/bluetooth/plugins/ | grep audio
If nothing shows, you need to install the bluetooth audio plugin package:
sudo apt install bluez-core bluez-alsa-utils # Debian/Ubuntu
sudo pacman -S bluez bluez-libs bluez-utils # Arch
Then restart bluetooth:
sudo systemctl restart bluetooth
Pair again with bluetoothctl:
bluetoothctl
power on
agent on
default-agent
scan on
pair XX:XX:XX:XX:XX:XX
connect XX:XX:XX:XX:XX:XX
trust XX:XX:XX:XX:XX:XX
The trust step is important — without it, the speaker might disconnect after reboot because Linux doesn't auto-trust new devices by default.
Quick-reference summary table
| Cause | Symptom | Fix |
|---|---|---|
| module-bluetooth-discover not loaded | Speaker pairs but no audio | pactl load-module module-bluetooth-discover + enable in default.pa |
| Wrong audio profile (HFP vs A2DP) | Speaker connects, music plays silently or mono | pactl set-card-profile bluez_card.XX a2dp_sink |
| Missing BlueZ audio plugin | Pairing fails at codec negotiation | Install bluez + bluetooth-utils, restart bluetooth |
Start with cause #1 — that fixes 80% of Bluetooth speaker pairing failures on modern Linux. If you're on a fresh Ubuntu 22.04 or 24.04 install, skip the bluetoothctl nonsense and go straight to PulseAudio. The module should be there but it's not loaded by default for reasons that still annoy me.
Was this solution helpful?