{"id":"1cc3e2f3ac1f6e03","repo":"rust-lang/cargo","slug":"maximum-limit-reached-when-reading","errorCode":null,"errorMessage":"maximum limit reached when reading","messagePattern":"maximum limit reached when reading","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"src/util/io.rs","lineNumber":19,"sourceCode":"use std::io::{self, Read, Take};\n\n#[derive(Debug)]\npub struct LimitErrorReader<R> {\n    inner: Take<R>,\n}\n\nimpl<R: Read> LimitErrorReader<R> {\n    pub fn new(r: R, limit: u64) -> LimitErrorReader<R> {\n        LimitErrorReader {\n            inner: r.take(limit),\n        }\n    }\n}\n\nimpl<R: Read> Read for LimitErrorReader<R> {\n    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n        match self.inner.read(buf) {\n            Ok(0) if self.inner.limit() == 0 => Err(io::Error::new(\n                io::ErrorKind::Other,\n                \"maximum limit reached when reading\",\n            )),\n            e => e,\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::LimitErrorReader;\n\n    use std::io::Read;\n\n    #[test]\n    fn under_the_limit() {\n        let buf = &[1; 7][..];\n        let mut r = LimitErrorReader::new(buf, 8);","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/util/io.rs#L1-L37","documentation":"Raised by `LimitErrorReader` (src/util/io.rs:19), a wrapper around `std::io::Read::take(limit)`. When the underlying reader still has data (`read` returned `Ok(0)` specifically because `self.inner.limit() == 0`, i.e. the take budget is exhausted mid-stream) the reader returns an `io::Error` with kind `Other` and this message. It enforces a hard ceiling on how many bytes cargo will ingest from a source.","triggerScenarios":"Reading a file/stream through `LimitErrorReader::new(r, limit)` where the source contains MORE than `limit` bytes. Once the take budget hits zero with data remaining, the next read yields this error rather than silently truncating.","commonSituations":"Downloading a `.crate` archive or index blob larger than the configured cap; a malicious/oversized registry response; a local file unexpectedly huge (corrupt or wrong file); cargo's download size limits engaged.","solutions":["Identify the oversized source (the error surfaces during a download/extract) and verify it is the intended file; replace a corrupt/wrong file.","Raise the applicable size limit if the large payload is legitimate (e.g. via the relevant config key or by using a different reader).","For registry operators, ensure the published artifact is within expected bounds."],"exampleFix":"// before\nlet mut r = LimitErrorReader::new(&data[..], 1024);\nr.read_to_end(&mut out)?; // fails if data.len() > 1024\n// after — size the limit to the real payload\nlet mut r = LimitErrorReader::new(&data[..], data.len() as u64);\nr.read_to_end(&mut out)?;","handlingStrategy":"validation","validationCode":"fn within_limit(len: u64, limit: u64) -> bool { len <= limit }\n// before wrapping a reader, check the expected payload size against the cap:\n// assert within_limit(metadata.len(), LIMIT)","typeGuard":null,"tryCatchPattern":"// Read with a soft limit and react to LimitErrorReader errors explicitly\nmatch r.read_to_end(&mut buf) {\n    Err(e) if e.to_string().contains(\"maximum limit reached\") => { /* truncate or reject */ }\n    r => r,\n}","preventionTips":["Size the LimitErrorReader budget to the real maximum expected payload.","Pre-validate file/download sizes before reading.","Treat the limit error as a security boundary, not a recoverable hiccup."],"tags":["cargo","io","reader","limit","download"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}