embassy-rs/embassy · error
zero-length write.
Error message
zero-length write.
What it means
The embedded-hal 0.2 blocking `Write::bwrite_all` implementation for `BufferedUartTx` treats a 0-byte result from `blocking_write` as an internal contract violation: the buffer was non-empty yet nothing was written and no error was returned, which would make the write loop spin forever. The library panics instead of looping infinitely.
Solutions
- Check UART/PIO configuration and error state before writing; ensure the buffered UART is properly initialized and the TX FIFO/queue is not wedged
- Clear any error conditions (framing/overrun) on the UART before retrying the write
- If writing generic code, prefer the embedded-hal 1.0 traits or embassy's native `blocking_write` API which returns errors instead of panicking on zero progress
- Update embassy-rp — zero-progress handling in the buffered UART has been the subject of fixes; a newer version may return Err instead
Defensive patterns
Strategy: try-catch
Try / catch
// e-h 0.2 traits don't support catchable panics; prefer the native API which returns Result
match tx.blocking_write(buf) {
Ok(n) if n == 0 => { /* treat as error: clear UART faults and retry */ }
Ok(_) => { /* progress */ }
Err(e) => { /* handle */ }
} Prevention
- Prefer embedded-hal 1.0 traits or embassy's native write APIs over the 0.2 compat layer
- Ensure the UART peer actually drains data (baud, wiring, flow control)
- Clear UART error flags periodically in buffered write loops
- Keep embassy-rp updated for buffered-UART zero-progress fixes
When it happens
Trigger: Calling `bwrite_all` (embedded-hal 0.2 blocking serial Write trait) when the underlying `blocking_write` returns Ok(0) — e.g. the buffered TX queue accepts/reports zero bytes written without an error, or a custom/latched error state that reports success with zero progress.
Common situations: Using the e-h-0.2 compatibility wrapper of buffered UART TX where the TX buffer is full in a way that yields zero writes; wiring `BufferedUartTx` into generic 0.2 serial code that loops on bwrite_all.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- unrecognized rx error
- UART DMA reported invalid `write_addr`
- Boot prepare error
- BufferedUarte UART overrun
- RTS and CTS pins must be either both set or none set.
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/1617fd2d13596dfe.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-rp/src/uart/buffered.rs:808
}
impl<'d> embedded_io::Write for BufferedUartTx<'d> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.blocking_write(buf)
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.blocking_flush()
}
}
impl<'d> embedded_hal_02::blocking::serial::Write<u8> for BufferedUartTx<'d> {
type Error = Error;
fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> {
while !buffer.is_empty() {
match self.blocking_write(buffer) {
Ok(0) => panic!("zero-length write."),
Ok(n) => buffer = &buffer[n..],
Err(e) => return Err(e),
}
}
Ok(())
}
fn bflush(&mut self) -> Result<(), Self::Error> {
self.blocking_flush()
}
}
impl<'d> embedded_hal_02::blocking::serial::Write<u8> for BufferedUart<'d> {
type Error = Error;
fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> {
while !buffer.is_empty() {
match self.blocking_write(buffer) {View on GitHub (pinned to 463a07b963)