embassy-rs/embassy · error

Bad mode

Error message

Bad mode

What it means

TxMode::register only supports the NonBuffered(waker) variant; when the transmit mode is Buffered or AnyId, registering a waker panics with 'Bad mode'. It surfaces when an async send on a bxCAN transmitter polls while the TX mode is not NonBuffered — the transmit state machine variant does not match the API used.

Solutions

  1. Match the transmit API to the configured mode: use queue-based send for Buffered mode, async send only for NonBuffered
  2. Drop all Transmitter handles before changing CAN configuration; never reconfigure while transmissions are in flight
  3. If reproducing with a single fixed configuration and current embassy-stm32, file a driver bug — this is an internal invariant violation
Defensive patterns

Strategy: validation

Validate before calling

// Rust: use the buffered transmitter's queue send API when split in buffered mode; reserve async send for NonBuffered transmitters.

Try / catch

// Rust: panics are not recoverable in no_std firmware; ensure transmit tasks are terminated before reconfiguration via structured concurrency or explicit abort.

Prevention

When it happens

Trigger: Polling/awaiting an async transmit whose TxMode::register is called while state.tx_mode is a Buffered/AnyId variant, typically after mode reconfiguration or mixing buffered transmitter APIs with non-buffered async sends.

Common situations: Holding a Transmitter handle across a runtime reconfiguration; using async send on a transmitter created in buffered mode; task races where one task re-splits the CAN while another transmits.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at embassy-stm32/src/can/bxcan/mod.rs:1130

                                _ = Registers(T::regs()).transmit(&frame);
                            }
                            Err(_) => {
                                break;
                            }
                        }
                    }
                }
            }
        });
    }

    fn register(&self, arg: &core::task::Waker) {
        match self {
            TxMode::NonBuffered(waker) => {
                waker.register(arg);
            }
            _ => {
                panic!("Bad mode");
            }
        }
    }
}

pub(crate) struct State {
    pub(crate) rx_mode: RxMode,
    pub(crate) tx_mode: TxMode,
    pub err_waker: AtomicWaker,
    receiver_instance_count: usize,
    sender_instance_count: usize,
}

impl State {
    pub const fn new() -> Self {
        Self {
            rx_mode: RxMode::NonBuffered(AtomicWaker::new()),
            tx_mode: TxMode::NonBuffered(AtomicWaker::new()),

View on GitHub (pinned to 463a07b963)