{"record":{"id":"47144fd6e64d7e4d","repo":"embassy-rs/embassy","slug":"the-write-size-for-the-concatenated-flashes-must-b","errorCode":null,"errorMessage":"The write size for the concatenated flashes must be the same","messagePattern":"The write size for the concatenated flashes must be the same","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-embedded-hal/src/flash/concat_flash.rs","lineNumber":27,"sourceCode":"pub struct ConcatFlash<First, Second>(First, Second);\n\nimpl<First, Second> ConcatFlash<First, Second> {\n    /// Create a new flash that concatenates two consecutive flashes.\n    pub fn new(first: First, second: Second) -> Self {\n        Self(first, second)\n    }\n}\n\nconst fn get_read_size(first_read_size: usize, second_read_size: usize) -> usize {\n    if first_read_size != second_read_size {\n        panic!(\"The read size for the concatenated flashes must be the same\");\n    }\n    first_read_size\n}\n\nconst fn get_write_size(first_write_size: usize, second_write_size: usize) -> usize {\n    if first_write_size != second_write_size {\n        panic!(\"The write size for the concatenated flashes must be the same\");\n    }\n    first_write_size\n}\n\nconst fn get_max_erase_size(first_erase_size: usize, second_erase_size: usize) -> usize {\n    let max_erase_size = if first_erase_size > second_erase_size {\n        first_erase_size\n    } else {\n        second_erase_size\n    };\n    if max_erase_size % first_erase_size != 0 || max_erase_size % second_erase_size != 0 {\n        panic!(\"The erase sizes for the concatenated flashes must have have a gcd equal to the max erase size\");\n    }\n    max_erase_size\n}\n\nimpl<First, Second, E> ErrorType for ConcatFlash<First, Second>\nwhere","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-embedded-hal/src/flash/concat_flash.rs#L9-L45","documentation":"The const fn `get_write_size` panics when the two flashes combined by `ConcatFlash::new` declare different WRITE_SIZE constants. A concatenated flash exposes a single write granularity, so mismatched write sizes are rejected. As a compile-time (const-eval) panic, it typically surfaces when instantiating the ConcatFlash type.","triggerScenarios":"`ConcatFlash::new(a, b)` where `First::WRITE_SIZE != Second::WRITE_SIZE`, evaluated by the NorFlash/AsyncNorFlash WRITE_SIZE computation.","commonSituations":"Mixing internal MCU flash (WRITE_SIZE 8/256) with SPI NOR flash (WRITE_SIZE 1 or 256); switching one flash to a chip with different page-write granularity; firmware version change that altered a driver's WRITE_SIZE.","solutions":["Choose two flashes whose WRITE_SIZE constants match","Wrap the odd flash in an adapter normalizing WRITE_SIZE to the shared value","Buffer writes so the effective write size is identical (e.g. page-buffer wrapper)","Review driver release notes for changed WRITE_SIZE constants after an update"],"exampleFix":"// before\ntype Boot = ConcatFlash<InternalFlash, SpiNor>; // WRITE_SIZE 256 vs 1\n// after\ntype Boot = ConcatFlash<InternalFlash, NorWrapper<256, SpiNor>>;","handlingStrategy":"validation","validationCode":"const fn write_sizes_match<A: NorFlash, B: NorFlash>() -> bool { A::WRITE_SIZE == B::WRITE_SIZE }\nconst _: () = assert!(write_sizes_match::<MyFlashA, MyFlashB>(), \"WRITE_SIZE mismatch for ConcatFlash\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Confirm WRITE_SIZE equality before ConcatFlash::new","Use a page-buffer wrapper to present a uniform write granularity","Pin and review driver versions so WRITE_SIZE constants don't change silently","Encode flash constants as board-level const items reused everywhere"],"tags":["embedded","flash","compile-time","panic","const-eval"],"backgroundTag":"invalid-config-value","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"}