embassy-rs/embassy · critical

alloc_endpoint_out failed

Error message

alloc_endpoint_out failed

What it means

The USB builder's alloc_endpoint_out forwards to the driver's endpoint allocator and expects success via `.expect`. The driver could not allocate an OUT endpoint with the requested type/address/packet size, usually because all hardware OUT endpoints are in use or the request is unsupported. This aborts the descriptor-building task.

Solutions

  1. Reduce the number of OUT endpoints in the class/composite configuration
  2. Pass `None` for ep_addr to let the driver pick a free endpoint
  3. Lower `max_packet_size` or use an endpoint type the hardware supports
  4. Check the driver/peripheral endpoint budget (e.g. OTG-FS supports fewer endpoints than HS) and adjust device selection

Example fix

// before
let ep = builder.endpoint_out(EndpointType::Bulk, Some(EndpointAddress::from_parts(0x01)), 512, 0);
// after
let ep = builder.endpoint_out(EndpointType::Bulk, None, 64, 0);
Defensive patterns

Strategy: validation

Validate before calling

// before building: count OUT endpoints in your classes
// and ensure count <= driver max OUT endpoints

Prevention

When it happens

Trigger: Calling `endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms)` on a Builder when the driver has no free OUT endpoint, the requested ep_addr is already allocated, or the type/size combination exceeds peripheral capabilities.

Common situations: Composite USB configurations with many OUT endpoints (CDC + MSC + HID + vendor) exceeding hardware endpoint count; explicit address collisions; requesting bulk with packet sizes unsupported by the peripheral.

Related errors


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

Appendix: source

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

        self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);

        ep
    }

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

    fn endpoint_out(
        &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::EndpointOut {
        let ep = self.alloc_endpoint_out(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)