linera-io/linera-protocol · error · LimitedWriterError

Writer limit exceeded

Error message

Writer limit exceeded

What it means

LimitedWriter wraps a std::io::Write and enforces a hard byte budget: each write checks that written + buf.len() stays within limit, using checked_sub so overflow also fails. Any single write that would cross the limit returns io::Error wrapping LimitedWriterError ('Writer limit exceeded') instead of a partial write, so the whole write is rejected.

Source

Thrown at linera-base/src/limited_writer.rs:35

    limit: usize,
    written: usize,
}

impl<W: Write> LimitedWriter<W> {
    pub fn new(inner: W, limit: usize) -> Self {
        Self {
            inner,
            limit,
            written: 0,
        }
    }
}

impl<W: Write> Write for LimitedWriter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        // Calculate the number of bytes we can write without exceeding the limit.
        // Fail if the buffer doesn't fit.
        ensure!(
            self.limit
                .checked_sub(self.written)
                .is_some_and(|remaining| buf.len() <= remaining),
            io::Error::other(LimitedWriterError)
        );
        // Forward to the inner writer.
        let n = self.inner.write(buf)?;
        self.written += n;
        Ok(n)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.inner.flush()
    }
}

#[cfg(test)]
mod tests {

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Raise the limit passed to LimitedWriter::new to fit the expected worst-case payload
  2. Reduce the data being written: paginate the query, drop unnecessary fields, or split into multiple capped writes
  3. Pre-compute the serialized size first and reject early with a clean error instead of failing mid-write

Example fix

// before
let mut w = LimitedWriter::new(&mut out, 1024); // payload is 2 KiB -> error

// after
let bytes = serde_json::to_vec(&value)?;
if bytes.len() > 1024 {
    return Err(anyhow::anyhow!("response too large: {}", bytes.len()));
}
out.write_all(&bytes)?;
Defensive patterns

Strategy: validation

Validate before calling

// Size the payload before writing through the cap
let bytes = serde_json::to_vec(&response)?;
if bytes.len() > LIMIT {
    return Err(anyhow::anyhow!("payload {} B exceeds cap {} B", bytes.len(), LIMIT));
}
writer.write_all(&bytes)?;

Try / catch

use linera_base::limited_writer::LimitedWriterError;
match writer.write_all(&buf) {
    Ok(()) => Ok(()),
    Err(e) if e.get_ref().and_then(|r| r.downcast_ref::<LimitedWriterError>()).is_some() => {
        Err(anyhow::anyhow!("response exceeded {LIMIT} byte cap; reduce payload"))
    }
    Err(e) => Err(e.into()),
}

Prevention

When it happens

Trigger: Serializing a value through a LimitedWriter (e.g. capping a JSON/bcs response payload) where the encoded output exceeds the limit; a single large write chunk crossing the remaining budget even though earlier writes fit.

Common situations: API/GraphQL response caps in linera services where a query returns more data than the configured cap; increasing an object's size (more chains, larger blobs) past a previously sufficient limit; tests using tiny limits (the unit test writes 6 bytes into a limit of 5).

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/c7ef36191c6c17bf. Report an issue: GitHub.