embassy-rs/embassy · error
unwrap of ` ` failed
Error message
unwrap of `{}` failed: {:?} What it means
embassy-nxp's internal `unwrap!` macro wraps an expression whose type implements `fmt::Try` (Result/Option) and, on Err/None, panics with the stringified expression and the Debug value of the error. It exists so embassy code and user code can unwrap with the embassy logger formatting (using `core::panic!` so it works without std). The message interpolates both the source expression text and the error payload.
Solutions
- Read the `{:?}` error payload in the message to identify the underlying error kind, then fix its cause.
- Replace `unwrap!` with explicit `match`/`?` handling in application code once past bring-up.
- Use the two-argument form `unwrap!(expr, "context")` to add context to the panic while debugging.
- For embedded error types with no Debug (defmt/std mismatch), ensure the error type implements the right Debug/Format trait for your logging feature set.
Example fix
// before
let byte = unwrap!(i2c.blocking_read(addr, &mut buf));
// after
match i2c.blocking_read(addr, &mut buf) {
Ok(()) => {}
Err(e) => { defmt::error!("i2c read failed: {:?}", e); return Err(e); }
} Defensive patterns
Strategy: try-catch
Validate before calling
// Replace blind unwrap with explicit handling at the call site:
if let Err(e) = i2c.blocking_write_read(addr, &mut cmd, &mut buf) {
defmt::warn!("i2c write_read failed: {:?}", e);
return Err(e.into());
} Type guard
fn is_ok<T, E>(r: &Result<T, E>) -> bool { r.is_ok() } Try / catch
// Embassy `unwrap!` panics and cannot be caught in embedded; handle Results before they reach unwrap!:
match op {
Ok(v) => use(v),
Err(e) => { defmt::error!("op failed: {:?}", e); recover_or_reset(); }
} Prevention
- Use unwrap! only during bring-up; migrate to `?`/match in production code paths.
- Always read the `{:?}` payload in the panic message to find the real error kind.
- Add the contextual form unwrap!(expr, "stage") so panics identify the failing init step.
- Wrap fallible peripheral operations in your own error type with recovery paths (retry, re-init).
When it happens
Trigger: Any call site (in embassy-nxp or user code using `embassy_nxp::fmt::unwrap!`) where the wrapped expression evaluates to `Err(e)` (or `None`); the panic message shows the expression string and `{:?}` of the error.
Common situations: Unwrapping peripheral init or operation Results that can legitimately fail (I2C NACK, timeout, invalid configuration); relying on unwrap during bring-up and then hitting a real runtime error instead of handling it.
Related errors
- unwrap of ` ` failed
- unwrap of ` ` failed
- unwrap of ` ` failed
- unwrap of ` ` failed
- unwrap of ` ` failed
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/c0f880e9e8c474b9.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-nxp/src/fmt.rs:215
};
}
#[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)