The Mystery of the Stuttering Buds
I love my Samsung Galaxy Buds 2 Pro. They sound great, the noise cancellation is solid, and they fit well enough that I forget I’m wearing them. Which is exactly what you want from earbuds until your operating system decides they shouldn’t work properly.
For weeks on the Capella-Outpost workstation running Argo OS, I had this maddening pattern: audio would play fine for about 30 seconds, stutter twice, drop out for a moment, reconnect, and then be fine for another minute or two before doing it again. Bluetooth connection drops mid-sentence during video calls. My coworker asking “are you still there?” for the third time while I fumble to switch to laptop speakers. Music cutting out during late-night coding sessions at exactly the moment you’ve gotten into a flow state. The worst part is you can never predict when the dropout happens, so you’re just sitting there waiting for it, which is the opposite of what music is supposed to do for you.
I tried everything that seemed reasonable. Re-pairing the buds. Removing them from BlueZ and starting fresh. Checking PipeWire configs. Switching between A2DP and HSP/HFP profiles. Googling error messages. I found forum posts from 2019 describing the exact same symptoms.
I wrote documentation about the fix. I wrote a script to apply the fix.
And today (Dec 28), I realized I never actually ran the script.
I’d had the fix sitting in my dotfiles repo for two weeks. Two weeks of stuttering audio. Two weeks of switching to wired headphones for calls. The documentation was beautiful. Clean markdown, step-by-step instructions, even a section header that said “Apply this fix.” I just… never did.
This is my most on-brand moment of the entire year.
The Culprit: ERTM
ERTM (Enhanced Retransmission Mode) is a Bluetooth L2CAP protocol feature. The idea is straightforward: when a packet gets lost during transmission, ERTM handles retransmission and reassembly. In theory, this makes Bluetooth connections more reliable. In practice, for a specific set of devices, it’s a disaster.
The problem is that some Bluetooth devices --- Samsung Galaxy Buds, certain Xbox wireless controllers, some Bose headphones --- don’t handle ERTM negotiation correctly. When the kernel offers ERTM, these devices either accept it and then choke on the retransmission protocol, or they get stuck in a negotiation loop that causes periodic connection resets. Either way, you get audio stuttering, input lag, or complete disconnects.
This isn’t a new issue. The kernel Bluetooth maintainers know about it. But disabling ERTM globally is a blunt instrument --- it works for broken devices but theoretically degrades reliability for devices that handle it properly. So it stays enabled by default, and people like me get to write blog posts about turning it off.
To check if ERTM is disabled (which you want):
cat /sys/module/bluetooth/parameters/disable_ertm
If it says N, ERTM is enabled. Mine said N. Mystery solved, two weeks late.
The Fix
We needed to force the kernel to disable ERTM for the Bluetooth module. Create (or edit) /etc/modprobe.d/bluetooth-usb.conf:
options bluetooth disable_ertm=1
One line. That’s it. One line that would have saved me two weeks of audio pain if I’d actually applied it when I wrote it down.
But here is the catch: writing the file doesn’t do anything until the module is reloaded. And reloading the Bluetooth module on a running system is not as simple as it sounds.
The Module Reload Dance
Your first instinct is:
sudo modprobe -r bluetooth
sudo modprobe bluetooth
This fails. The bluetooth module has dependencies --- other modules that are loaded on top of it and actively using it. btusb (the USB Bluetooth driver), bnep (Bluetooth network encapsulation), rfcomm (serial port emulation), and several vendor-specific modules like btintel, btrtl, btmtk, and btbcm. The kernel won’t unload bluetooth while any of these are sitting on top of it.
You have to tear down the entire stack, from the top down, and then rebuild it:
# Stop the bluetooth service first
sudo rc-service bluetooth stop
# Unload the entire module stack (order matters - dependents first)
sudo modprobe -r bnep rfcomm btusb btrtl btmtk btintel btbcm bluetooth
# Reload with new parameters
sudo modprobe bluetooth btusb
# Restart the service
sudo rc-service bluetooth start
The order matters. If you try to unload bluetooth before btusb, the kernel refuses because btusb depends on it. You work your way down the dependency tree: remove the leaves first, then the branches, then the trunk.
After this sequence, checking the parameter again:
cat /sys/module/bluetooth/parameters/disable_ertm
Now it says Y. Paired the Galaxy Buds. Crystal clear AAC audio. No stuttering. No dropouts. Sat there for 20 minutes waiting for the glitch that never came.
Testing Everything Else
The paranoid part of my brain (the part that runs Gentoo by choice) wanted to make sure disabling ERTM didn’t break my other Bluetooth devices. I spent an evening connecting everything I own:
- Galaxy Buds 2 Pro: perfect, obviously.
- Bluetooth keyboard: still works, no input lag difference.
- Phone file transfer (OBEX): still works.
- Xbox controller via Bluetooth: actually works better. It had been having occasional input drops that I’d blamed on interference. Turns out ERTM was the culprit there too.
Nothing broke. Every device I tested either worked the same or worked better. Which tracks with what the kernel bug reports say --- the devices that handle ERTM correctly don’t really benefit from it in practice. The retransmission overhead on modern Bluetooth is minimal enough that the basic mode handles packet loss fine.
Automating the Pain Away
Since I clearly can’t be trusted to run my own fix scripts manually, I decided to bake this into the Argo OS installer. The next person to install Argo OS (which is probably just me on a different machine, but still) shouldn’t have to discover this the hard way.
The commander-os-install.sh script now:
- Downloads the configuration repository.
- Applies system configs --- including writing
/etc/modprobe.d/bluetooth-usb.conf--- automatically during first boot. - Clones the config repo to the user’s home directory for reference.
The Bluetooth fix is just one of a handful of kernel module tweaks that the installer applies. There’s also a vm.swappiness adjustment and some I/O scheduler tuning. Small things that make Argo OS feel right on the Capella-Outpost hardware. The point is: if I’ve hit a problem once and found the fix, the installer should make sure I never hit it again on a fresh setup.
Now, a fresh install of Argo OS comes with working Bluetooth out of the box. The fix is applied before anyone even pairs their first device.
Documentation is great. Automation is better. But documentation you write and then ignore for two weeks while your earbuds stutter during every video call? That’s a special kind of self-inflicted suffering that I hope to never repeat.
The script was right there. In my dotfiles. With a comment that said # APPLY THIS. Past Me even knew Present Me would forget.