embassy-rs/embassy · error

Consecutive read operations are not supported!

Error message

Consecutive read operations are not supported!

What it means

The TWIM (I2C master) driver's transaction helper validates the operation sequence before programming the peripheral. The nRF TWIM hardware cannot perform two back-to-back receive transactions because a repeated-start must be issued between reads, and the driver does not synthesize one automatically. Instead of mis-sequencing DMA transfers, it panics with this message. Callers must merge consecutive reads or insert a write between them.

Solutions

  1. Merge the consecutive reads into a single Operation::Read with one buffer sized to hold all expected bytes.
  2. If the device requires separate reads, split into two separate transactions (issuing a STOP between them).
  3. Reorder operations so a Write separates the two Read operations if the device protocol allows repeated start with write in between.
  4. Split into two separate transactions (each read gets its own START/STOP).

Example fix

// before
let mut ops = [Operation::Write(&[0x00]), Operation::Read(&mut buf1), Operation::Read(&mut buf2)];
twim.blocking_transaction(addr, &mut ops)?;
// after
let mut combined = [0u8; buf1.len() + buf2.len()];
let mut ops = [Operation::Write(&[0x00]), Operation::Read(&mut combined)];
twim.blocking_transaction(addr, &mut ops)?;
// then split `combined` into buf1/buf2
Defensive patterns

Strategy: validation

Validate before calling

fn validate_ops(ops: &[Operation]) -> bool {
    ops.windows(2).all(|w| !matches!(w, [Operation::Read(_), Operation::Read(_)]))
}
assert!(validate_ops(&ops), "consecutive reads unsupported on TWIM");

Type guard

fn has_consecutive_reads(ops: &[Operation]) -> bool {
    ops.windows(2).any(|w| matches!(w, [Operation::Read(_), Operation::Read(_)]))
}

Prevention

When it happens

Trigger: Calling `twim.blocking_transaction`, `blocking_transaction_timeout`, or `transaction` with an operations slice beginning with `[Operation::Read(..), Operation::Read(..), ..]` — i.e. two or more Operation::Read entries where the first two are adjacent.

Common situations: Porting code that issued register-write then multi-chunk reads as separate operations; sensor drivers that read several register banks in one transaction; converting blocking read() calls into a multi-operation transaction and listing two reads back to back.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at embassy-nrf/src/twim.rs:434

        if inten {
            r.intenset().write(|w| {
                w.set_suspended(true);
                w.set_stopped(true);
                w.set_error(true);
            });
        } else {
            r.intenclr().write(|w| {
                w.set_suspended(true);
                w.set_stopped(true);
                w.set_error(true);
            });
        }

        assert!(!operations.is_empty());
        match operations {
            [Operation::Read(_), Operation::Read(_), ..] => {
                panic!("Consecutive read operations are not supported!")
            }
            [Operation::Read(rd_buffer), Operation::Write(wr_buffer), rest @ ..] => {
                let stop = rest.is_empty();

                // Set up DMA buffers.
                unsafe {
                    self.set_tx_buffer(wr_buffer)?;
                    self.set_rx_buffer(rd_buffer)?;
                }

                r.shorts().write(|w| {
                    w.set_lastrx_dma_tx_start(true);
                    if stop {
                        w.set_lasttx_stop(true);
                    } else {
                        w.set_lasttx_suspend(true);
                    }
                });

View on GitHub (pinned to 463a07b963)