{"record":{"id":"27bffa9f8bc9683b","repo":"embassy-rs/embassy","slug":"invalid-out-length","errorCode":null,"errorMessage":"invalid OUT length {}","messagePattern":"invalid OUT length (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/usb/usb.rs","lineNumber":168,"sourceCode":"    r.set_ctr_tx(true); // don't clear\n    r.set_dtog_rx(false); // don't toggle\n    r.set_dtog_tx(false); // don't toggle\n    r.set_stat_rx(Stat::from_bits(0));\n    r.set_stat_tx(Stat::from_bits(0));\n    r\n}\n\nfn align_len_up(len: u16) -> u16 {\n    ((len as usize + USBRAM_ALIGN - 1) / USBRAM_ALIGN * USBRAM_ALIGN) as u16\n}\n\n// Returns (actual_len, len_bits)\nfn calc_out_len(len: u16) -> (u16, u16) {\n    match len {\n        // NOTE: this could be 2..=62 with 16bit USBRAM, but not with 32bit. Limit it to 60 for simplicity.\n        2..=60 => (align_len_up(len), align_len_up(len) / 2 << 10),\n        61..=1024 => ((len + 31) / 32 * 32, (((len + 31) / 32 - 1) << 10) | 0x8000),\n        _ => panic!(\"invalid OUT length {}\", len),\n    }\n}\n\n#[cfg(not(any(usbram_32_2048, usbram_32_1024)))]\nmod btable {\n    use super::*;\n\n    pub(super) fn write_in_tx<T: Instance>(index: usize, addr: u16) {\n        USBRAM.mem(index * 4 + 0).write_value(addr);\n    }\n\n    pub(super) fn write_in_rx<T: Instance>(index: usize, addr: u16) {\n        USBRAM.mem(index * 4 + 2).write_value(addr);\n    }\n\n    pub(super) fn write_in_len_rx<T: Instance>(index: usize, _addr: u16, len: u16) {\n        USBRAM.mem(index * 4 + 3).write_value(len);\n    }","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/usb/usb.rs#L150-L186","documentation":"calc_out_len encodes an OUT endpoint's buffer size into the 16-bit USBRAM size field; the btable encoding only supports 2–60 bytes (small windows) or 61–1024 bytes (32-byte blocks). Requesting an OUT endpoint buffer outside 2..=1024 has no hardware encoding, so the driver panics at allocation time (via alloc_endpoint).","triggerScenarios":"Calling usb_dev.alloc_endpoint(EndpointType::Bulk/Interrupt/Isochronous, max_packet_size = 0 or 1, or > 1024) on the btable-based usb.rs driver; also 0-byte OUT allocations fall into the wildcard arm.","commonSituations":"Passing wMaxPacketSize straight from a descriptor that is 0 or misparsed; requesting USB3-era 2048-byte packets on classic btable parts (max 1024); typos like 10 instead of 64 (still fine) vs 1 instead of 10 (panics).","solutions":["Use a max_packet_size between 2 and 1024 bytes for OUT endpoints (typically 8/16/32/64 for FS)","Clamp requested sizes: size.clamp(2, 1024) before calling alloc_endpoint","For 2048-byte HS needs, switch to a part/driver variant using usbram_32 (usb_host-style path) that supports larger sizes","Check where the size value originates (descriptor parse, config constant) and validate it there"],"exampleFix":"// before\nlet ep_out = dev.alloc_endpoint(EndpointType::Bulk, 0, 64)?; // IN=0 ok, OUT=0 panics if used for OUT\nlet ep_out = dev.alloc_endpoint(EndpointType::Bulk, 2048, 2048)?; // OUT 2048 panics\n// after\nlet ep_out = dev.alloc_endpoint(EndpointType::Bulk, 64, 64)?; // both within 2..=1024","handlingStrategy":"validation","validationCode":"fn out_len_ok(len: u16) -> bool { (2..=1024).contains(&len) }\n// before alloc_endpoint: assert!(out_len_ok(out_size));","typeGuard":"fn valid_out_size(len: u16) -> bool { (2..=1024).contains(&len) }","tryCatchPattern":null,"preventionTips":["Clamp OUT sizes to 2..=1024 before allocation","Use standard FS packet sizes (8/16/32/64) unless you need larger","Validate sizes parsed from descriptors instead of passing raw values","Remember btable parts cap OUT buffers at 1024, not 2048"],"tags":["embedded","stm32","usb","endpoint","allocation","panic"],"backgroundTag":"value-out-of-range","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}