embassy-rs/embassy · error

Partition offset must be a multiple of read, write and…

Error message

Partition offset must be a multiple of read, write and erase size

What it means

`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.

Solutions

  1. Align the offset to T::ERASE_SIZE (the dominant constraint) before constructing the partition
  2. Define offsets as multiples of the flash's erase sector size in a shared layout module
  3. Verify with a const assertion that offset % T::ERASE_SIZE == 0 in your layout code
  4. Recompute all partition offsets after any change of underlying flash hardware

Example fix

// before
let part = BlockingPartition::new(&flash, 512, 4096); // 512 not multiple of ERASE_SIZE 4096
// after
let part = BlockingPartition::new(&flash, 4096, 4096); // aligned
Defensive patterns

Strategy: validation

Validate before calling

const fn blocking_offset_ok<T: NorFlash>(offset: u32) -> bool {
    offset % T::READ_SIZE as u32 == 0
        && offset % T::WRITE_SIZE as u32 == 0
        && offset % T::ERASE_SIZE as u32 == 0
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/ce8cd1db1e332253. Report an issue: GitHub.

Appendix: source

Thrown at embassy-embedded-hal/src/flash/partition/blocking.rs:37

    size: u32,
}

impl<'a, M: RawMutex, T: NorFlash> Clone for BlockingPartition<'a, M, T> {
    fn clone(&self) -> Self {
        Self {
            flash: self.flash,
            offset: self.offset,
            size: self.size,
        }
    }
}

impl<'a, M: RawMutex, T: NorFlash> BlockingPartition<'a, M, T> {
    /// Create a new partition
    pub const fn new(flash: &'a Mutex<M, RefCell<T>>, offset: u32, size: u32) -> Self {
        if offset % T::READ_SIZE as u32 != 0 || offset % T::WRITE_SIZE as u32 != 0 || offset % T::ERASE_SIZE as u32 != 0
        {
            panic!("Partition offset must be a multiple of read, write and erase size");
        }
        if size % T::READ_SIZE as u32 != 0 || size % T::WRITE_SIZE as u32 != 0 || size % T::ERASE_SIZE as u32 != 0 {
            panic!("Partition size must be a multiple of read, write and erase size");
        }
        Self { flash, offset, size }
    }

    /// Get the partition offset within the flash
    pub const fn offset(&self) -> u32 {
        self.offset
    }

    /// Get the partition size
    pub const fn size(&self) -> u32 {
        self.size
    }
}

View on GitHub (pinned to 463a07b963)