embassy-rs/embassy · error

unwrap of ` ` failed

Error message

unwrap of `{}` failed: {}: {:?}

What it means

This is the context-carrying variant of embassy-net-wiznet's `unwrap!` macro (non-defmt build): `unwrap!(expr, "message", args...)`. When `expr` is `Err` or `None`, it panics printing the stringified expression, the caller-supplied context message, and the debug-formatted error value. The extra `format_args!` text comes from the call site to pinpoint which operation failed.

Solutions

  1. Read the context message in the panic output to locate the failing operation, then find that `unwrap!(..., "ctx")` call in embassy-net-wiznet sources.
  2. Fix the root cause: verify SPI wiring, clock speed, chip select, and that the W5500 is properly reset and powered.
  3. Handle the error path explicitly at the call site instead of unwrapping if failures are expected in your environment.
  4. Enable `defmt` logging to get better diagnostics on constrained targets.

Example fix

// before
let reg = unwrap!(self.read_reg(Reg::PHYCFGR), "read phycfgr");
// after
let reg = self.read_reg(Reg::PHYCFGR).map_err(|_| Error::Spi)?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check the operation the context label names, e.g. SPI bus:
if !self.spi_ok().await { return Err(Error::Spi); }

Type guard

fn is_ok<T, E>(r: &Result<T, E>) -> bool { r.is_ok() }

Try / catch

// Use a panic hook that records the context message (second field of the panic) to identify the failing subsystem, then perform a safe device reset.

Prevention

When it happens

Trigger: Any call to `unwrap!(expr, "ctx", ...)` in the wiznet W5500 driver where `expr` yields `Err(e)` or `None` — the second panic arm at fmt.rs:197 fires only when the caller passed extra message arguments.

Common situations: Embedded firmware using the Wiznet Ethernet driver hits a failed SPI/queue/register operation while a context label (e.g. "spi transfer", "fifo read") is attached, usually during bring-up of new hardware or after a bus glitch.

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


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/84bc622943d20ed9. Report an issue: GitHub.

Appendix: source

Thrown at embassy-net-wiznet/src/fmt.rs:197

    };
}

#[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;
    type Error;
    fn into_result(self) -> Result<Self::Ok, Self::Error>;
}

impl<T> Try for Option<T> {
    type Ok = T;
    type Error = NoneError;

View on GitHub (pinned to 463a07b963)