Skip to content

Commit b5478e9

Browse files
committed
post: publish wireguard post
1 parent 965e165 commit b5478e9

File tree

1 file changed

+14
-14
lines changed

1 file changed

+14
-14
lines changed

content/posts/2026-02-23-wireplumber-volume-reset.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
+++
2-
title = 'Debugging a WirePlumber volume reset on boot'
2+
title = 'Debugging WirePlumber volume reset on boot'
33
date = 2026-02-23T09:00:00Z
4-
draft = true
4+
draft = false
55
tags = ['nixos', 'linux', 'audio', 'pipewire', 'debugging']
66
+++
77

8-
Every boot, my volume came up at 100%. I could turn it down during a session and it would stay put, but the next reboot it was back to blasting. Annoying enough to actually dig into.
8+
Recently I noticed that my volume was at 100% after rebooting my desktop NixOS machine. My audio setup runs through a Schiit Fulla DAC over USB, nothing exotic, just a clean external DAC for headphones. I could turn the volume down during a session and it would stay put, but the next reboot it was back at full blast. It wasn't anything big but it was annoying enough to actually dig into.
99

1010
## First hypothesis: stale state files
1111

12-
WirePlumber saves volume state to `~/.local/state/wireplumber/`. The obvious first suspect was a stale or corrupt state file. Checking the files, `restore-stream` hadn't been modified since June 2024a clear sign something was off. This turned out to be an old WirePlumber 0.4.x format file that 0.5.x no longer writes to, but was still reading from on boot. It had `volume=1.0` baked in.
12+
WirePlumber saves volume state to `~/.local/state/wireplumber/`. The obvious first suspect was a stale or corrupt state file. Checking the files, `restore-stream` hadn't been modified since June 2024, a clear sign something was off. This turned out to be an old [WirePlumber 0.4.x format](https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/migration.html) file that 0.5.x no longer writes to, but was still reading from on boot. It had `volume=1.0` baked in.
1313

14-
Cleared the whole state directory and restarted WirePlumber. Set the volume, rebooted. Still 100%.
14+
I cleared the whole state directory and restarted WirePlumber, set the volume to 50% and rebooted. Still came up at 100%.
1515

1616
## The pavucontrol clue
1717

@@ -21,33 +21,33 @@ The most useful observation came from restarting WirePlumber manually:
2121
systemctl --user restart wireplumber
2222
```
2323

24-
Volume goes to 100%. Then opening `pavucontrol`without touching any controls — silently drops it back to 50%.
24+
This causes the volume to go 100% every time. Then opening `pavucontrol`, without touching any controls, causes it to silently drop back to 50%.
2525

2626
That told me the saved state was fine and the restore mechanism worked. It just wasn't triggering at init time. The volume was only being applied when a PulseAudio client connected.
2727

2828
## ALSA mixer failures
2929

30-
Looking at the WirePlumber journal with debug logging enabled, every restart showed the same errors: `spa.alsa: Unable to load mixer: Broken pipe`. With verbose output, all 12 errors were exclusively on `hw:3`the Schiit Fulla DACacross four retry cycles during ACP profile probing. The other three cards (HDMI, onboard, webcam) attached to their mixers without issue.
30+
I enabled debug logging on WirePlumber and checked the journal. Every restart showed the same errors: `spa.alsa: Unable to load mixer: Broken pipe`. With verbose output, all 12 errors were exclusively on `hw:3`, the Schiit Fulla DAC, across four retry cycles during [ACP profile probing](https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/alsa.html). The other three cards (HDMI, onboard, webcam) attached to their mixers without issue.
3131

32-
This matters because WirePlumber uses the ALSA mixer handle to apply saved route volumes to the device. No mixer, no volume restore. The fallback is the hardware default 1.0.
32+
WirePlumber uses the ALSA mixer handle to apply [saved route volumes](https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/settings.html) to the device. No mixer, no volume restore. The fallback is the hardware default, 1.0.
3333

34-
The `pavucontrol` workaround worked because it goes through the PipeWire/PA compat layer rather than the ALSA mixer path, which successfully applied the saved state.
34+
That also explained why the `pavucontrol` workaround worked. It goes through the PipeWire/PA compat layer rather than the ALSA mixer path, which successfully applied the saved state.
3535

3636
## Tracing it to the kernel
3737

38-
The kernel log had one relevant line, logged 9 seconds after the Schiit enumerated:
38+
I checked the kernel log and found one relevant line, logged 9 seconds after the Schiit enumerated:
3939

4040
```
4141
usb 1-5.4.3: 17:0: failed to get current value for ch 0 (-32)
4242
```
4343

44-
Error `-32` is `EPIPE` Broken Pipe at the USB level. The `snd_usb_audio` driver tried to send a `GET_CUR` control request to read the current volume from the device's feature unit, the USB endpoint stalled, and that permanently broke the ALSA mixer handle for the rest of the session.
44+
Error `-32` is `EPIPE`, meaning Broken Pipe at the USB level. The [`snd_usb_audio`](https://docs.kernel.org/sound/alsa-configuration.html#module-snd-usb-audio) driver tried to send a `GET_CUR` control request to read the current volume from the device's feature unit. The USB endpoint stalled, and that permanently broke the ALSA mixer handle for the rest of the session.
4545

46-
Confirmed this by running `amixer -c 3 info` later in the session — still returning `Broken pipe`, long after boot. Not a timing issue, a permanent stall.
46+
I confirmed this by running `amixer -c 3 info` later in the session. Still returning `Broken pipe`, long after boot. Not a timing issue, a permanent stall.
4747

4848
## The fix
4949

50-
`snd_usb_audio` has a module parameter for exactly this: `ignore_ctl_error=1`. It tells the driver to log and continue when a USB audio control request fails, rather than stalling the endpoint. With it set, the EPIPE is recorded but the mixer handle stays usable, WirePlumber can attach to it, and volume state is saved and restored correctly.
50+
It turns out `snd_usb_audio` has a [module parameter](https://docs.kernel.org/sound/alsa-configuration.html#module-snd-usb-audio) for exactly this: `ignore_ctl_error=1`. It tells the driver to log and continue when a USB audio control request fails, rather than stalling the endpoint. With it set, the EPIPE is recorded but the mixer handle stays usable, WirePlumber can attach to it, and volume state is saved and restored correctly.
5151

5252
In NixOS this goes in `boot.extraModprobeConfig`:
5353

@@ -57,7 +57,7 @@ boot.extraModprobeConfig = ''
5757
'';
5858
```
5959

60-
Reboot, volume came up at 50%. Fixed.
60+
I rebooted and the volume came up at 50%. Fixed.
6161

6262
## What was actually happening
6363

0 commit comments

Comments
 (0)