{"record":{"id":"ce8cd1db1e332253","repo":"embassy-rs/embassy","slug":"partition-offset-must-be-a-multiple-of-read-write-ce8cd1","errorCode":null,"errorMessage":"Partition offset must be a multiple of read, write and erase size","messagePattern":"Partition offset 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/blocking.rs","lineNumber":37,"sourceCode":"    size: u32,\n}\n\nimpl<'a, M: RawMutex, T: NorFlash> Clone for BlockingPartition<'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> BlockingPartition<'a, M, T> {\n    /// Create a new partition\n    pub const fn new(flash: &'a Mutex<M, RefCell<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","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-embedded-hal/src/flash/partition/blocking.rs#L19-L55","documentation":"`BlockingPartition::new` is the blocking (RefCell-based) counterpart of the async Partition and performs the identical const-time validation: the offset must be a multiple of the flash's READ_SIZE, WRITE_SIZE and ERASE_SIZE, otherwise it panics. Because the constructor is const, the panic occurs during const evaluation of the partition definition.","triggerScenarios":"Calling `BlockingPartition::new(&mutex_flash, offset, size)` where `offset % T::READ_SIZE != 0 || offset % T::WRITE_SIZE != 0 || offset % T::ERASE_SIZE != 0` — e.g. offset 0x100 on a flash with WRITE_SIZE 8 and ERASE_SIZE 4096 that isn't a 4096 multiple.","commonSituations":"Settings/OTA storage partitions placed at arbitrary byte offsets; layouts copied from a datasheet's byte map that ignores sector granularity; changing the backing flash to one with larger erase sectors without moving partitions.","solutions":["Align the offset to T::ERASE_SIZE (the dominant constraint) before constructing the partition","Define offsets as multiples of the flash's erase sector size in a shared layout module","Verify with a const assertion that offset % T::ERASE_SIZE == 0 in your layout code","Recompute all partition offsets after any change of underlying flash hardware"],"exampleFix":"// before\nlet part = BlockingPartition::new(&flash, 512, 4096); // 512 not multiple of ERASE_SIZE 4096\n// after\nlet part = BlockingPartition::new(&flash, 4096, 4096); // aligned","handlingStrategy":"validation","validationCode":"const fn blocking_offset_ok<T: NorFlash>(offset: u32) -> bool {\n    offset % T::READ_SIZE as u32 == 0\n        && offset % T::WRITE_SIZE as u32 == 0\n        && offset % T::ERASE_SIZE as u32 == 0\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Align offsets to the flash's ERASE_SIZE before constructing BlockingPartition","Reuse the same layout constants between async and blocking partitions","Add const assertions in the settings/storage module for offset alignment","Audit offsets after any change of backing flash hardware or sector size"],"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"}