embassy-rs/embassy · critical

alloc_endpoint_in failed

Error message

alloc_endpoint_in failed

What it means

The USB builder's alloc_endpoint_in forwards to the driver's endpoint allocator and expects success via `.expect`. The driver returned None/Err, meaning it could not allocate an IN endpoint with the requested type/address/packet size — typically because the hardware's endpoint pool is exhausted or the request is unsupported. This aborts the descriptor-building task.

Solutions

  1. Reduce the number of IN endpoints in the class/composite configuration
  2. Remove explicit `ep_addr` (Some(addr)) values so the driver can assign free endpoints automatically
  3. Lower `max_packet_size` or change `ep_type` to one supported by the driver
  4. Check the driver's max endpoint count / feature flags (e.g. embassy-stm32 synopsys-otg endpoint counts) and pick a chip variant with more endpoints

Example fix

// before
let ep = builder.endpoint_in(EndpointType::Bulk, Some(EndpointAddress::from_parts(0x81)), 512, 0);
// after
let ep = builder.endpoint_in(EndpointType::Bulk, None, 64, 0); // let driver assign a free IN endpoint
Defensive patterns

Strategy: validation

Validate before calling

// before building: count IN endpoints in your classes
// and ensure count <= driver max IN endpoints (check chip datasheet / driver docs)

Prevention

When it happens

Trigger: Calling `endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms)` on a Builder when the underlying USB driver has no free IN endpoint, or the requested ep_addr is already claimed, or the max_packet_size/ep_type combination is unsupported by hardware.

Common situations: Declaring many IN endpoints (multiple CDC-ACM interfaces, MIDI, UAC2, vendor bulk endpoints) exceeding the peripheral's endpoint count (e.g. 8 on some STM32 parts); requesting an explicit address that collides; wrong feature config limiting endpoint pool size.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/1e43f46a90d38190. Report an issue: GitHub.

Appendix: source

Thrown at embassy-usb/src/builder.rs:540

        self.builder
            .config_descriptor
            .endpoint(endpoint, synchronization_type, usage_type, extra_fields);
    }

    /// Allocate an IN endpoint, without writing its descriptor.
    ///
    /// Used for granular control over the order of endpoint and descriptor creation.
    pub fn alloc_endpoint_in(
        &mut self,
        ep_type: EndpointType,
        ep_addr: Option<EndpointAddress>,
        max_packet_size: u16,
        interval_ms: u8,
    ) -> D::EndpointIn {
        self.builder
            .driver
            .alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms)
            .expect("alloc_endpoint_in failed")
    }

    fn endpoint_in(
        &mut self,
        ep_type: EndpointType,
        ep_addr: Option<EndpointAddress>,
        max_packet_size: u16,
        interval_ms: u8,
        synchronization_type: SynchronizationType,
        usage_type: UsageType,
        extra_fields: &[u8],
    ) -> D::EndpointIn {
        let ep = self.alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms);
        self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);

        ep
    }

View on GitHub (pinned to 463a07b963)