{"record":{"id":"c1f20888e189d3ca","repo":"embassy-rs/embassy","slug":"called-capability-not-between-bos-and-end-bos","errorCode":null,"errorMessage":"called `capability` not between `bos` and `end_bos`.","messagePattern":"called `capability` not between `bos` and `end_bos`\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-usb/src/descriptor.rs","lineNumber":432,"sourceCode":"                0x00, 0x00, // wTotalLength\n                0x00, // bNumDeviceCaps\n            ],\n            &[],\n        );\n\n        self.capability(capability_type::USB_2_0_EXTENSION, &[0; 4]);\n    }\n\n    /// Writes capability descriptor to a BOS\n    ///\n    /// # Arguments\n    ///\n    /// * `capability_type` - Type of a capability\n    /// * `data` - Binary data of the descriptor\n    pub fn capability(&mut self, capability_type: u8, data: &[u8]) {\n        match self.num_caps_mark {\n            Some(mark) => self.writer.buf[mark] += 1,\n            None => panic!(\"called `capability` not between `bos` and `end_bos`.\"),\n        }\n\n        let mut start = self.writer.position;\n        let blen = data.len();\n\n        assert!(\n            (start + blen + 3) <= self.writer.buf.len() && (blen + 3) <= 255,\n            \"Descriptor buffer full\"\n        );\n\n        self.writer.buf[start] = (blen + 3) as u8;\n        self.writer.buf[start + 1] = descriptor_type::CAPABILITY;\n        self.writer.buf[start + 2] = capability_type;\n\n        start += 3;\n        self.writer.buf[start..start + blen].copy_from_slice(data);\n        self.writer.position = start + blen;\n    }","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-usb/src/descriptor.rs#L414-L450","documentation":"`capability()` appends a BOS device-capability descriptor and increments the bNumDeviceCaps counter whose location was recorded by `bos()`. If `capability()` is invoked when no BOS container is open, the counter mark is None and the writer panics rather than produce a malformed BOS descriptor.","triggerScenarios":"Calling `DescriptorWriter::capability()` outside the span between `bos()` and `end_bos()` calls on the same writer.","commonSituations":"Adding USB capabilities (e.g. WebUSB, Microsoft OS 2.0) in the wrong descriptor callback; forgetting the `end_bos()`/`bos()` pair when restructuring custom descriptor code; calling capability during configuration-descriptor building instead of BOS building.","solutions":["Call `capability(...)` only between `writer.bos()` and `writer.end_bos()`.","Move capability writes into the BOS-descriptor path of your class implementation.","Ensure `bos()`/`end_bos()` are called exactly once as an enclosing pair.","Refactor custom classes so capability registration goes through the proper hook that opens the BOS writer."],"exampleFix":"// before\nfn get_configuration_descriptors(&self, w: &mut DescriptorWriter) {\n    w.capability(0x06, &cap_data)?; // outside BOS\n}\n// after\nfn get_bos_descriptors(&self, w: &mut BosWriter) {\n    w.bos();\n    w.capability(0x06, &cap_data)?;\n    w.end_bos();\n    Ok(())\n}","handlingStrategy":"validation","validationCode":"fn get_bos_descriptors(&self, w: &mut BosWriter) -> Result<(), DescriptorError> {\n    w.bos();               // opens the BOS container\n    w.capability(CAP_TYPE_WEBUSB, &CAP_DATA)?; // only valid here\n    w.end_bos();\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call capability() strictly between bos() and end_bos()","Put capability descriptors in the BOS callback, never in configuration/device callbacks","Keep bos/end_bos paired exactly once per descriptor build","Compare against the WebUSB/WinUSB embassy-usb examples for correct placement"],"tags":["usb","embedded","panic","descriptor-builder"],"backgroundTag":"invalid-state-transition","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"}