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

  1. Remove the duplicate channel from the `channels` slice passed to Speaker::new.
  2. Ensure each channel variant has a unique ChannelConfig bit.
  3. 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

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


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)