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
- Call `BootLoader::try_prepare` instead of `prepare` and handle the Err case explicitly
- Verify the ACTIVE/DFU/STATE partition offsets and sizes match the linker memory layout
- Erase/initialize the STATE partition to a known-good value on first boot
- 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
- Prefer try_prepare over prepare in production boot code
- Keep ACTIVE/DFU/STATE partitions aligned with the linker script
- Erase the STATE partition during provisioning/first boot
- Log the underlying flash error from try_prepare during development
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)