embassy-rs/embassy · error
Invalid transmission power value
Error message
Invalid transmission power value
What it means
set_transmission_power panics when the requested dBm value is not one of the discrete power levels supported by the nRF radio: +8, +4, 0, -4, -8, -12, -16, -20, -30, or -40 dBm. The hardware has a fixed enum of TX power settings, so arbitrary intermediate values cannot be encoded.
Solutions
- Snap the requested power to the nearest supported level: [+8, +4, 0, -4, -8, -12, -16, -20, -30, -40] dBm.
- Write a helper that maps any i8 to the closest valid level before calling set_transmission_power.
- Validate config values at startup against the supported list rather than passing them through.
Example fix
// before radio.set_transmission_power(power_dbm); // e.g. -3, panics // after const LEVELS: [i8; 10] = [8, 4, 0, -4, -8, -12, -16, -20, -30, -40]; let snapped = *LEVELS.iter().min_by_key(|l| (l - power_dbm).abs()).unwrap(); radio.set_transmission_power(snapped);
Defensive patterns
Strategy: validation
Validate before calling
const TX_LEVELS: [i8; 10] = [8, 4, 0, -4, -8, -12, -16, -20, -30, -40];
assert!(TX_LEVELS.contains(&power_dbm), "unsupported TX power {}", power_dbm);
radio.set_transmission_power(power_dbm); Type guard
fn is_supported_tx_power(dbm: i8) -> bool {
matches!(dbm, 8 | 4 | 0 | -4 | -8 | -12 | -16 | -20 | -30 | -40)
} Prevention
- Snap arbitrary dBm values to the nearest supported level before calling.
- Store TX power as a constants enum, not a free i8.
- Convert config units carefully; only the listed steps are hardware-representable.
When it happens
Trigger: Calling ieee802154::Radio::set_transmission_power with any value other than the supported levels — e.g. set_transmission_power(-3), set_transmission_power(5), or a computed/config value like power = -2*iB.
Common situations: Porting drivers from radios with continuous or different power steps; computing power dynamically from link-quality feedback without snapping to a supported level; config files written in different units (e.g. -3 dBm) instead of the supported steps.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Bad 802.15.4 channel
- Boot prepare error
- unwrap of ` ` failed
- unwrap of ` ` failed
- Task is already in use
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/70a79265ba2a364b.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-nrf/src/radio/ieee802154.rs:198
-1 => TxPower::Neg1dBm,
#[cfg(feature = "_nrf5340-net")]
-2 => TxPower::Neg2dBm,
#[cfg(feature = "_nrf5340-net")]
-3 => TxPower::Neg3dBm,
-4 => TxPower::Neg4dBm,
#[cfg(feature = "_nrf5340-net")]
-5 => TxPower::Neg5dBm,
#[cfg(feature = "_nrf5340-net")]
-6 => TxPower::Neg6dBm,
#[cfg(feature = "_nrf5340-net")]
-7 => TxPower::Neg7dBm,
-8 => TxPower::Neg8dBm,
-12 => TxPower::Neg12dBm,
-16 => TxPower::Neg16dBm,
-20 => TxPower::Neg20dBm,
-30 => TxPower::Neg30dBm,
-40 => TxPower::Neg40dBm,
_ => panic!("Invalid transmission power value"),
};
r.txpower().write(|w| w.set_txpower(tx_power));
}
/// Waits until the radio state matches the given `state`
fn wait_for_radio_state(&self, state: RadioState) {
while self.state() != state {}
}
/// Get the current radio state
fn state(&self) -> RadioState {
self.r.state().read().state()
}
/// Moves the radio from any state to the DISABLED state
fn disable(&mut self) {
let r = self.r;View on GitHub (pinned to 463a07b963)