diff --git a/crates/headroom-core/src/pw/registry.rs b/crates/headroom-core/src/pw/registry.rs index c271c60..c4f5904 100644 --- a/crates/headroom-core/src/pw/registry.rs +++ b/crates/headroom-core/src/pw/registry.rs @@ -1485,7 +1485,20 @@ impl RoutingState { if id == node_id { tracing::debug!(node_id, name, "real sink removed from registry"); let mut s = self.daemon.lock(); - if s.real_sink.node_id == Some(node_id) { + // Clear BOTH name and node_id when the departing + // sink is our preferred real sink. Just nulling + // node_id (the previous behaviour) left the name + // pinned to a sink that no longer exists, so + // `apply_pending_routes` would queue every bypass + // route forever against a stale target name. The + // F4 fallback or a fresh `default.audio.sink` event + // can then pick a replacement. + if s.real_sink.name.as_deref() == Some(name.as_str()) { + s.real_sink.name = None; + s.real_sink.node_id = None; + } else if s.real_sink.node_id == Some(node_id) { + // Defensive: id matched but name didn't (sinks + // shouldn't double-register). Null the id. s.real_sink.node_id = None; } false