{"record":{"id":"240f5cc007124de7","repo":"embassy-rs/embassy","slug":"partition-size-must-be-a-multiple-of-read-write-a","errorCode":null,"errorMessage":"Partition size must be a multiple of read, write and erase size","messagePattern":"Partition size must be a multiple of read, write and erase size","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-embedded-hal/src/flash/partition/asynch.rs","lineNumber":39,"sourceCode":"impl<'a, M: RawMutex, T: NorFlash> Clone for Partition<'a, M, T> {\n    fn clone(&self) -> Self {\n        Self {\n            flash: self.flash,\n            offset: self.offset,\n            size: self.size,\n        }\n    }\n}\n\nimpl<'a, M: RawMutex, T: NorFlash> Partition<'a, M, T> {\n    /// Create a new partition\n    pub const fn new(flash: &'a Mutex<M, T>, offset: u32, size: u32) -> Self {\n        if offset % T::READ_SIZE as u32 != 0 || offset % T::WRITE_SIZE as u32 != 0 || offset % T::ERASE_SIZE as u32 != 0\n        {\n            panic!(\"Partition offset must be a multiple of read, write and erase size\");\n        }\n        if size % T::READ_SIZE as u32 != 0 || size % T::WRITE_SIZE as u32 != 0 || size % T::ERASE_SIZE as u32 != 0 {\n            panic!(\"Partition size must be a multiple of read, write and erase size\");\n        }\n        Self { flash, offset, size }\n    }\n\n    /// Get the partition offset within the flash\n    pub const fn offset(&self) -> u32 {\n        self.offset\n    }\n\n    /// Get the partition size\n    pub const fn size(&self) -> u32 {\n        self.size\n    }\n}\n\nimpl<M: RawMutex, T: NorFlash> ErrorType for Partition<'_, M, T> {\n    type Error = Error<T::Error>;\n}","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-embedded-hal/src/flash/partition/asynch.rs#L21-L57","documentation":"The same `Partition::new` constructor also validates that the partition SIZE is a multiple of READ_SIZE, WRITE_SIZE and ERASE_SIZE. A size that isn't sector-aligned would leave a trailing partial sector the underlying flash cannot erase or program atomically, so the const constructor panics.","triggerScenarios":"Calling `Partition::new(&mutex_flash, offset, size)` where `size % T::READ_SIZE != 0`, `size % T::WRITE_SIZE != 0`, or `size % T::ERASE_SIZE != 0` — e.g. a 100 KiB partition on a flash with 4 KiB erase (100 KiB is fine) vs a 100 KiB partition with 64 KiB erase sectors (not a multiple).","commonSituations":"Sizing partitions to exact image byte lengths instead of sector multiples; dividing a flash evenly leaving a non-aligned remainder; reusing layouts across chips with different sector sizes.","solutions":["Round the size up to a multiple of T::ERASE_SIZE","Express partition sizes in erase sectors: size = n * T::ERASE_SIZE","Add a build-time assert comparing your layout constants with the flash's erase size","Adjust adjacent partitions so the total still covers the flash exactly"],"exampleFix":"// before\nlet part = Partition::new(&flash, 0, 100 * 1024); // 100 KiB not multiple of 64 KiB erase\n// after\nlet part = Partition::new(&flash, 0, 128 * 1024); // multiple of 64 KiB","handlingStrategy":"validation","validationCode":"const fn size_aligned<T: NorFlash>(size: u32) -> bool {\n    size % T::READ_SIZE as u32 == 0\n        && size % T::WRITE_SIZE as u32 == 0\n        && size % T::ERASE_SIZE as u32 == 0\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Round partition sizes up to erase-sector multiples","Size images to fit whole sectors; pad the image, not the partition","Const-assert partition sizes against T::ERASE_SIZE in layout code","Ensure consecutive partitions tile the flash exactly after rounding"],"tags":["embedded","flash","partition","panic","alignment"],"backgroundTag":"invalid-argument-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"}