rust-lang/cargo · error · io::Error

maximum limit reached when reading

Error message

maximum limit reached when reading

What it means

`LimitErrorReader` wraps an inner reader with `take(limit)`, capping total bytes read. On each `read`, if the underlying read returns `Ok(0)` AND the remaining limit has hit `0` (`self.inner.limit() == 0`), the reader returns an `io::Error` (kind `Other`, message `"maximum limit reached when reading"`) instead of a clean EOF. This converts a silent truncation into an explicit error so callers cannot mistake a size-limited stream for a complete one.

Solutions

  1. Increase the configured read limit if the input is legitimately large and trusted.
  2. Verify the upstream source is not returning an unexpectedly large or malicious payload.
  3. Ensure the stream is not being read twice or chained in a way that double-counts bytes against the limit.

Example fix

// before
let mut r = LimitErrorReader::new(source, 1024 * 1024);
// reading >1MiB -> Err("maximum limit reached when reading")

// after
let mut r = LimitErrorReader::new(source, 64 * 1024 * 1024);
Defensive patterns

Strategy: try-catch

Validate before calling

// before wrapping, confirm the expected size is within the budget
fn within_budget(expected: u64, limit: u64) -> Result<(), String> {
    if expected > limit { return Err(format!("expected {expected} exceeds limit {limit}")); }
    Ok(())
}

Try / catch

match reader.read_to_end(&mut buf) {
    Ok(n) => { /* complete read within limit */ }
    Err(e) if e.to_string().contains("maximum limit reached when reading") => {
        // handle truncated/oversized input: raise the limit or reject the source
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Reading from a `LimitErrorReader` past its configured byte budget: the inner `take(limit)` exhausts the limit, the next `read` yields `Ok(0)`, and `limit() == 0` — so the reader signals the cap as an error rather than EOF.

Common situations: Parsing a downloaded file (e.g. crate `.crate` archive, registry index, lockfile) where Cargo imposes a size guard against pathologically large inputs; an upstream server returning a payload larger than the configured cap; or a corrupted/truncated download that exceeds an expected bound.

Related errors


AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11). Data as JSON: /api/errors/1cc3e2f3ac1f6e03. Report an issue: GitHub.

Appendix: source

Thrown at src/util/io.rs:19

use std::io::{self, Read, Take};

#[derive(Debug)]
pub struct LimitErrorReader<R> {
    inner: Take<R>,
}

impl<R: Read> LimitErrorReader<R> {
    pub fn new(r: R, limit: u64) -> LimitErrorReader<R> {
        LimitErrorReader {
            inner: r.take(limit),
        }
    }
}

impl<R: Read> Read for LimitErrorReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match self.inner.read(buf) {
            Ok(0) if self.inner.limit() == 0 => Err(io::Error::new(
                io::ErrorKind::Other,
                "maximum limit reached when reading",
            )),
            e => e,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::LimitErrorReader;

    use std::io::Read;

    #[test]
    fn under_the_limit() {
        let buf = &[1; 7][..];
        let mut r = LimitErrorReader::new(buf, 8);

View on GitHub (pinned to eb98b54bc9)