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
- Merge the consecutive reads into a single Operation::Read with one buffer sized to hold all expected bytes.
- If the device requires separate reads, split into two separate transactions (issuing a STOP between them).
- Reorder operations so a Write separates the two Read operations if the device protocol allows repeated start with write in between.
- 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
- Build a helper that coalesces adjacent Read operations into one buffered read before calling transaction APIs.
- Model I2C transactions as write-then-read pairs, which is what most devices actually require.
- Write a unit test over your operation builders asserting no adjacent reads.
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
- Boot prepare error
- unwrap of ` ` failed
- unwrap of ` ` failed
- Task is already in use
- Event is already in use
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)