embassy-rs/embassy · error
Invalid GPIO port index
Error message
Invalid GPIO port index {} What it means
Panic in InputFuture::poll: the future's waker registry (GPIO_WAKERS) is sized for the number of GPIO ports the chip actually has. When polling, the pin's port index is checked against the table length; a port value at or beyond that length cannot have a registered waker, so interrupt-driven waiting is impossible and the code panics rather than silently never waking. The faulting input is a pin constructed with an out-of-range port number — a pin model/peripheral mismatch or an invalid port passed into GPIO configuration.
Solutions
- Use only pin definitions from the generated embassy-imxrt peripherals model for the actual chip variant
- Check that the Cargo feature/board model matches the physical chip so GPIO_WAKERS covers all real ports
- Fix code that fabricates pins with hand-written port numbers instead of using the peripherals struct
- Validate port index at pin-construction time so invalid pins fail early, not during poll
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at embassy-imxrt/src/gpio.rs:446 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/7ca608aea210f37e.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-imxrt/src/gpio.rs:446
// Enable pin interrupt on GPIO INT A
pin.block()
.intena(pin.port())
.modify(|r, w| unsafe { w.int_en().bits(r.int_en().bits() | (1 << pin.pin())) });
});
Self { pin: pin.into() }
}
}
impl Future for InputFuture<'_> {
type Output = ();
fn poll(self: FuturePin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// We need to register/re-register the waker for each poll because any
// calls to wake will deregister the waker.
if self.pin.port() >= GPIO_WAKERS.len() {
panic!("Invalid GPIO port index {}", self.pin.port());
}
let port_waker = GPIO_WAKERS[self.pin.port()];
if port_waker.is_none() {
panic!("Waker not present for GPIO port {}", self.pin.port());
}
let waker = port_waker.unwrap().get_waker(self.pin.pin());
if waker.is_none() {
panic!(
"Waker not present for GPIO pin {}, port {}",
self.pin.pin(),
self.pin.port()
);
}
waker.unwrap().register(cx.waker());
// Double check that the pin interrut has been disabled by IRQ handlerView on GitHub (pinned to 463a07b963)