embassy-rs/embassy · critical

Boot prepare error

Error message

Boot prepare error

What it means

embassy-boot-nrf's `prepare` calls `try_prepare` and panics with "Boot prepare error" if the bootloader state cannot be processed. `try_prepare` fails when inspecting or mutating the boot swap state (active/DFU/state flash partitions) returns an error, e.g. unreadable or misaligned flash. The panic exists so the failure is routed through defmt logging rather than a hidden expect.

Solutions

  1. Call `BootLoader::try_prepare` instead of `prepare` and handle the Err case explicitly
  2. Verify the ACTIVE/DFU/STATE partition offsets and sizes match the linker memory layout
  3. Erase/initialize the STATE partition to a known-good value on first boot
  4. Check the underlying NorFlash error from try_prepare to identify the failing partition

Example fix

// before
let loader = BootLoader::prepare(config);
// after
let loader = match BootLoader::try_prepare::<ACTIVE, DFU, STATE>(config) {
    Ok(l) => l,
    Err(e) => { defmt::error!("boot prepare failed: {:?}", e); fallback_boot(); }
};
Defensive patterns

Strategy: try-catch

Validate before calling

fn partitions_sane(active: (u32, u32), dfu: (u32, u32), state: (u32, u32)) -> bool {
    let ok = |(off, len): (u32, u32)| off % 4096 == 0 && len % 4096 == 0;
    ok(active) && ok(dfu) && ok(state)
}

Try / catch

match BootLoader::try_prepare::<ACTIVE, DFU, STATE>(config) {
    Ok(loader) => loader,
    Err(e) => { defmt::error!("boot prepare: {:?}", e); enter_safe_boot(); }
};

Prevention

When it happens

Trigger: Constructing a `BootLoader` via `BootLoader::prepare(BootLoaderConfig { .. })` at startup when `try_prepare` returns Err: bad state magic/corrupted state partition, NorFlash read/write/erase errors on the active, DFU, or STATE partitions, or misconfigured partition boundaries.

Common situations: First boot after flashing a fresh DFU partition with garbage state; state partition not erased before first use; wrong partition sizes/offsets in BootLoaderConfig; flash driver erroring due to wrong memory-mapped region on nRF.

Related errors


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

Appendix: source

Thrown at embassy-boot-nrf/src/lib.rs:28

};
use embassy_nrf::nvmc::PAGE_SIZE;
use embassy_nrf::{Peri, wdt};
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};

/// A bootloader for nRF devices.
pub struct BootLoader<const BUFFER_SIZE: usize = PAGE_SIZE>;

impl<const BUFFER_SIZE: usize> BootLoader<BUFFER_SIZE> {
    /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
    pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
        config: BootLoaderConfig<ACTIVE, DFU, STATE>,
    ) -> Self {
        if let Ok(loader) = Self::try_prepare::<ACTIVE, DFU, STATE>(config) {
            loader
        } else {
            // Use explicit panic instead of .expect() to ensure this gets routed via defmt/etc.
            // properly
            panic!("Boot prepare error")
        }
    }

    /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
    pub fn try_prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
        config: BootLoaderConfig<ACTIVE, DFU, STATE>,
    ) -> Result<Self, BootError> {
        let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
        let mut boot = embassy_boot::BootLoader::new(config);
        let _state = boot.prepare_boot(aligned_buf.as_mut())?;
        Ok(Self)
    }

    /// Boots the application without softdevice mechanisms.
    ///
    /// # Safety
    ///
    /// This modifies the stack pointer and reset vector and will run code placed in the active partition.

View on GitHub (pinned to 463a07b963)