embassy-rs/embassy · error
Invalid channel config, duplicate channel
Error message
Invalid channel config, duplicate channel {}. What it means
The UAC1 speaker class validates that each requested channel occupies a distinct bit in the 16-bit channel configuration mask. If two channels map to the same configuration bit (a duplicate), the resulting audio descriptor would be ambiguous, so Speaker::new panics naming the duplicated mask value.
Solutions
- Remove the duplicate channel from the `channels` slice passed to Speaker::new.
- Ensure each channel variant has a unique ChannelConfig bit.
- Pre-validate the list with the same mask-and-check logic before constructing the Speaker.
Example fix
// before let channels = &[Channel::FrontLeft, Channel::FrontLeft, Channel::FrontRight]; // after let channels = &[Channel::FrontLeft, Channel::FrontRight, Channel::FrontCenter];
Defensive patterns
Strategy: validation
Validate before calling
fn channels_are_unique(channels: &[Channel]) -> bool {
let mut mask: u16 = 0;
channels.iter().all(|c| {
let bit: u16 = c.get_channel_config().into();
if mask & bit != 0 { return false; }
mask |= bit;
true
})
}
assert!(channels_are_unique(&channels)); Type guard
fn channels_are_unique(channels: &[Channel]) -> bool {
let mut mask: u16 = 0;
channels.iter().all(|c| {
let bit: u16 = c.get_channel_config().into();
if mask & bit != 0 { return false; }
mask |= bit;
true
})
} Prevention
- Deduplicate the channel list before Speaker::new
- Keep one ChannelConfig bit per channel variant
- Test descriptor generation for each channel layout you ship
When it happens
Trigger: Calling Speaker::new with a channel list containing two channels whose get_channel_config() bits overlap — e.g. the same channel repeated, or two variant channels sharing a flag.
Common situations: Hand-assembling channel arrays for multi-channel (5.1/7.1) setups; accidentally including a channel twice; custom ChannelConfig impls returning overlapping bits.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unsupported EP0 size
- if composite_with_iads is set, you must set device_class =…
- invalid max_packet_size_0, the allowed values are 8, 16, 32…
- AHB frequency is too low
- SAI failed to enable. Check that config is valid (frame…
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/a6533650a29e27ed.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-usb/src/class/uac1/speaker.rs:146
let control_interface = interface.interface_number();
let streaming_interface = u8::from(control_interface) + 1;
let mut alt = interface.alt_setting(USB_AUDIO_CLASS, USB_AUDIOCONTROL_SUBCLASS, PROTOCOL_NONE, None);
// Terminal topology:
// Input terminal (receives audio stream) -> Feature Unit (mute and volume) -> Output terminal (e.g. towards speaker)
// =======================================
// Input Terminal Descriptor [UAC 3.3.2.1]
// Audio input
let terminal_type: u16 = TerminalType::UsbStreaming.into();
// Assemble channel configuration field
let mut channel_config: u16 = ChannelConfig::None.into();
for channel in channels {
let channel: u16 = channel.get_channel_config().into();
if channel_config & channel != 0 {
panic!("Invalid channel config, duplicate channel {}.", channel);
}
channel_config |= channel;
}
let input_terminal_descriptor = [
INPUT_TERMINAL, // bDescriptorSubtype
INPUT_UNIT_ID, // bTerminalID
terminal_type as u8,
(terminal_type >> 8) as u8, // wTerminalType
0x00, // bAssocTerminal (none)
channels.len() as u8, // bNrChannels
channel_config as u8,
(channel_config >> 8) as u8, // wChannelConfig
0x00, // iChannelNames (none)
0x00, // iTerminal (none)
];
// ========================================View on GitHub (pinned to 463a07b963)