embassy-rs/embassy · error
unwrap of ` ` failed
Error message
unwrap of `{}` failed: {:?} What it means
This panic comes from embassy-net-wiznet's internal `unwrap!` macro (the non-defmt variant) when the expression passed to `unwrap!(...)` is an `Err` or `None`. The macro converts the value via `fmt::Try::into_result` and, on failure, panics with the stringified expression and the debug-formatted error. It is a deliberate fail-fast on operations the driver assumed could not fail or that the caller was expected to handle.
Solutions
- Identify the real `unwrap!` call site: the panic string includes the stringified expression; search embassy-net-wiznet/src for that expression.
- Fix the underlying cause (usually SPI bus errors, wrong chip-select/speed wiring, or missing device reset) rather than the unwrap itself.
- Enable the `defmt` feature if you want `defmt::unwrap!` semantics and richer logging in embedded builds.
- As a last resort, fork/patch the driver to propagate the error instead of unwrapping.
Example fix
// before: driver panics inside unwrap! let res = unwrap!(self.spi.read_write(&mut buf[..]), "spi read_write"); // after: propagate SPI errors instead of panicking let res = self.spi.read_write(&mut buf[..]).map_err(|_| Error::Spi)?;
Defensive patterns
Strategy: try-catch
Validate before calling
// In no_std/panic=abort firmware you cannot catch; pre-validate hardware state:
if !self.device_ready() { return Err(Error::Spi); } Type guard
fn is_ok<T, E>(r: &Result<T, E>) -> bool { r.is_ok() } Try / catch
// Firmware: set a panic hook to log the unwrap expression and reset/defuse. #[panic_handler] or `panic_hook`: log panic info, then reset the W5500 and reinit SPI.
Prevention
- Verify SPI wiring, chip-select, and clock speed against W5500 datasheet limits before bring-up.
- Add a reset-and-reinit routine for the Ethernet chip on first failure.
- Enable defmt logging to see driver internals before failures escalate to unwrap panics.
- Patch or wrap driver calls to propagate errors instead of unwrapping.
When it happens
Trigger: Any call to `unwrap!(expr)` in the wiznet driver where `expr: Result<T,E>` is `Err(e)` or `expr: Option<T>` is `None` — e.g. unwrapping SPI transfer results, buffer queue pops, or device register reads during W5500 Ethernet chip operations.
Common situations: Bare-metal/embassy firmware using the Wiznet W5500 driver where an SPI transaction failed, the chip was miswired/reset, or an internal buffer/queue returned None. Because this is the `not(feature = "defmt")` build, the panic message prints via core fmt instead of defmt.
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
- unwrap of ` ` failed
- unwrap of ` ` failed
- unwrap of ` ` failed
- Can only take the executor once
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/20603e944b39e606.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-net-wiznet/src/fmt.rs:189
};
}
#[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)