embassy-rs/embassy · error

unwrap of ` ` failed

Error message

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

What it means

This panic comes from embassy-rp's custom `unwrap!` macro (defined via the `fmt` module's Try::into_result). It fires when an expression expected to be Ok/TryResult-success actually returned an Err, and prints the expression text, a user-supplied message, and the error's Debug representation. It is embassy's panic-with-context replacement for `.unwrap()` on embedded fallible APIs.

Solutions

  1. Read the `{:?}` error value in the panic message; it names the underlying Err variant
  2. Fix the configuration that made the unwrapped expression fail (wrong pin, pin already taken, invalid params)
  3. Replace `unwrap!` with `match`/`?` or try_ variant APIs to handle the error instead of panicking
  4. Check embassy-rp examples for the API you call to see required pin/feature setup

Example fix

// before
let pio = unwrap!(peri.pio(), "pio error");
// after
let pio = match peri.pio() {
    Ok(p) => p,
    Err(e) => defmt::error!("pio setup failed: {:?}", e),
};
Defensive patterns

Strategy: try-catch

Validate before calling

// validate before unwrap
let res = peri.fallible_init();
if res.is_err() { defmt::error!("init failed: {:?}", res.unwrap_err()); }

Type guard

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

Try / catch

match embassy_rp::fmt::Try::into_result(expr) {
    Ok(v) => use(v),
    Err(e) => defmt::error!("expr failed: {:?}", e),
}

Prevention

When it happens

Trigger: Calling `unwrap!(some_fallible_expr, "message")` in embassy-rp code (e.g. GPIO, DMA, I2C setup helpers) where the inner expression returns Err — such as unwrap!(peri.gpio().into_pull_type_input(...)) style calls or any macro-based unwrap around a Result/TRY result.

Common situations: Invalid pin/peripheral configuration passed to a macro-wrapped initializer (wrong pin, double-use of a peripheral), or a HAL call that returned a ConfigError/Either error being blindly unwrapped in example-style code.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at embassy-rp/src/fmt.rs:210

    };
}

#[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)