embassy-rs/embassy · error
unwrap of ` ` failed
Error message
unwrap of `{}` failed: {:?} What it means
embassy-rp's `unwrap!` macro wraps a `Result`/`Option`-returning expression and panics with a debug dump of the error when it is `Err`/`None`, replacing plain `.unwrap()` to give better diagnostics in a `no_std`/defmt environment. Any embassy-rp internal or user code path using this macro on a failing expression produces this panic.
Solutions
- Inspect the `{:?}` debug value in the panic to identify the inner error type and variant
- Locate the failing call site from the stringified expression in the panic message
- Handle the Result at the call site with `?`, `match`, or `map_err` instead of unwrapping
- Fix the underlying hardware/configuration issue the inner error indicates (wrong pins, missing pull-ups, busy bus)
Example fix
// before
let byte = unwrap!(spi.blocking_read(&mut buf));
// after
let byte = spi.blocking_read(&mut buf).map_err(|e| {
defmt::error!("spi read failed: {:?}", e);
e
})?;
Defensive patterns
Strategy: try-catch
Validate before calling
fn unwrap_or_log<T, E: core::fmt::Debug>(r: Result<T, E>) -> Option<T> {
match r { Ok(t) => Some(t), Err(e) => { defmt::error!("op failed: {:?}", e); None } }
}
Type guard
fn is_ok<T, E>(r: &Result<T, E>) -> bool { r.is_ok() }
Prevention
- Propagate HAL Results with ? instead of unwrapping
- Log the Debug output of inner errors before any unwrap
- Handle expected hardware errors (NACK, timeout) explicitly
- Audit unwrap! usage when porting code between HAL versions
When it happens
Trigger: Any `unwrap!(expr)` call in embassy-rp where the expression returns `Err(e)` (via `fmt::Try::into_result`), such as peripheral init, GPIO, SPI/I2C calls, or embedded-hal operations returning embedded-hal errors.
Common situations: Failed peripheral operations (e.g. SPI transfer error, I2C NACK) being force-unwrapped in driver internals; user code adopting the embassy-rp `unwrap!` macro on fallible HAL calls; version drift where a call that used to return a plain value now returns Result.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- unwrap of ` ` failed
- timer must be stopped before setting counter
- Failed to configure PLL_SYS
- Failed to configure PLL_USB
- DMA: error on DMA_0 channel
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/037f4fa2820528e0.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-rp/src/fmt.rs:202
};
}
#[cfg(feature = "defmt")]
#[collapse_debuginfo(yes)]
macro_rules! unwrap {
($($x:tt)*) => {
::defmt::unwrap!($($x)*)
};
}
#[cfg(not(feature = "defmt"))]
#[collapse_debuginfo(yes)]
macro_rules! unwrap {
($arg:expr) => {
match $crate::fmt::Try::into_result($arg) {
::core::result::Result::Ok(t) => t,
::core::result::Result::Err(e) => {
::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
}
}
};
($arg:expr, $($msg:expr),+ $(,)? ) => {
match $crate::fmt::Try::into_result($arg) {
::core::result::Result::Ok(t) => t,
::core::result::Result::Err(e) => {
::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
}
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct NoneError;
pub trait Try {
type Ok;View on GitHub (pinned to 463a07b963)