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
- Read the `{:?}` error value in the panic message; it names the underlying Err variant
- Fix the configuration that made the unwrapped expression fail (wrong pin, pin already taken, invalid params)
- Replace `unwrap!` with `match`/`?` or try_ variant APIs to handle the error instead of panicking
- 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
- Prefer try_/fallible APIs over unwrap! macros in production code
- Log the Debug error value before deciding how to recover
- Copy pin setup from the official embassy examples for your board
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
- 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/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)