embassy-rs/embassy · critical
Boot prepare error
Error message
Boot prepare error
What it means
embassy-boot-stm32's `prepare` panics with "Boot prepare error" if `try_prepare` fails. try_prepare inspects the bootloader state and performs required pre-boot actions (firmware swap) across the ACTIVE/DFU/STATE NorFlash partitions, optionally using an aligned BUFFER. Any flash error or invalid state triggers this panic, routed via defmt instead of expect.
Solutions
- Use `BootLoader::try_prepare::<ACTIVE, DFU, STATE, BUFFER_SIZE>` and handle Err explicitly
- Verify partition offsets/sizes against the STM32 flash bank layout and linker script
- Ensure BUFFER_SIZE meets the required write-granularity for your STM32 family
- Erase or rewrite the STATE partition to a valid state on provisioning
Example fix
// before
let loader = BootLoader::prepare(config);
// after
let loader = match BootLoader::try_prepare::<ACTIVE, DFU, STATE, BUFFER_SIZE>(config) {
Ok(l) => l,
Err(e) => { defmt::error!("prepare failed: {:?}", e); recover(); }
}; Defensive patterns
Strategy: try-catch
Validate before calling
const BUFFER_SIZE: usize = 4096; // must be >= flash write granularity
fn partitions_ok(p: [(u32, u32); 3]) -> bool {
p.iter().all(|&(off, len)| off % 2048 == 0 && len % 2048 == 0)
} Try / catch
match BootLoader::try_prepare::<ACTIVE, DFU, STATE, BUFFER_SIZE>(config) {
Ok(l) => l,
Err(e) => { defmt::error!("prepare failed: {:?}", e); boot_recovery_image(); }
}; Prevention
- Use try_prepare so flash errors are observable instead of a panic
- Match BUFFER_SIZE to the STM32 family's write granularity (e.g. 8 bytes on F4, 64+ on others)
- Keep partition constants generated from one source of truth shared with the linker script
- Provision the STATE partition during factory flashing
When it happens
Trigger: Calling `BootLoader::prepare(BootLoaderConfig { .. })` when try_prepare returns Err: invalid/corrupted state magic in the STATE partition, NorFlash errors on any partition, or a BUFFER_SIZE too small / misconfigured partitions on STM32 internal flash.
Common situations: First boot after OTA image write with stale state; partition layout in BootLoaderConfig not matching the flash bank layout; buffer size smaller than the flash write granularity.
Related errors
- Boot prepare error
- Boot prepare error
- ZeroCopyPubSub cannot have multiple subscribers
- WatchdogChannels::All is not supported for AWD2; use…
- WatchdogChannels::All is not supported for AWD2; use…
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/14c0df512fe15c9a.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-boot-stm32/src/lib.rs:29
use embedded_storage::nor_flash::NorFlash;
/// A bootloader for STM32 devices.
pub struct BootLoader {
/// The reported state of the bootloader after preparing for boot
pub state: State,
}
impl BootLoader {
/// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>(
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
) -> Self {
if let Ok(loader) = Self::try_prepare::<ACTIVE, DFU, STATE, BUFFER_SIZE>(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, const BUFFER_SIZE: usize>(
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 { state })
}
/// Boots the application.
///
/// # Safety
///
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.View on GitHub (pinned to 463a07b963)