{"record":{"id":"69d45983a4beb830","repo":"quickwit-oss/tantivy","slug":"unexpectedeof-69d459","errorCode":"UnexpectedEof","errorMessage":"failed to fill whole buffer","messagePattern":"failed to fill whole buffer","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"ownedbytes/src/lib.rs","lineNumber":233,"sourceCode":"            Ok(buf_len)\n        } else {\n            buf[..data_len].copy_from_slice(self.data);\n            self.data = &[];\n            Ok(data_len)\n        }\n    }\n    #[inline]\n    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {\n        buf.extend(self.data);\n        let read_len = self.data.len();\n        self.data = &[];\n        Ok(read_len)\n    }\n    #[inline]\n    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {\n        let read_len = self.read(buf)?;\n        if read_len != buf.len() {\n            return Err(io::Error::new(\n                io::ErrorKind::UnexpectedEof,\n                \"failed to fill whole buffer\",\n            ));\n        }\n        Ok(())\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::io::{self, Read};\n\n    use super::OwnedBytes;\n\n    #[test]\n    fn test_owned_bytes_debug() {\n        let short_bytes = OwnedBytes::new(b\"abcd\".as_ref());\n        assert_eq!(","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/ownedbytes/src/lib.rs#L215-L251","documentation":"OwnedBytes implements std::io::ReadExact; this error is thrown when read_exact was asked to fill a buffer of N bytes but the underlying bytes/mmap only supplied fewer. It is tantivy's typed UnexpectedEof for short reads on in-memory owned byte slices.","triggerScenarios":"read_exact called on an OwnedBytes whose length is smaller than the requested buffer size: deserializing a struct from a byte slice shorter than needed, slicing a file with an out-of-range range (e.g. bytes.slice(0, huge_len)), or reading past the end of a mmap-backed segment.","commonSituations":"Hand-written deserialization tests (as in test_owned_bytes_read) requesting more bytes than the fixture contains; corrupted/truncated segment files whose header advertises more data than exists; off-by-one in slice arithmetic when parsing custom file formats.","solutions":["Check the byte-slice length before calling read_exact and size the buffer to the available data","Regenerate or re-fetch the truncated/corrupted file","In tests, make the fixture buffer at least as large as what read_exact requests","Review range/slice computations (slice offsets, header length constants) for off-by-one errors"],"exampleFix":"// before\nlet mut buf = [0u8; 8];\nbytes.read_exact(&mut buf)?; // panics/errors if bytes.len() < 8\n// after\nlet mut buf = [0u8; 8];\nif bytes.len() < 8 {\n    return Err(io::Error::new(io::ErrorKind::UnexpectedEof, \"need 8 bytes\"));\n}\nbytes.read_exact(&mut buf)?;","handlingStrategy":"validation","validationCode":"if bytes.len() < needed { return Err(io::Error::new(io::ErrorKind::UnexpectedEof, \"too short\")); }","typeGuard":null,"tryCatchPattern":"match read_exact_result {\n    Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {\n        eprintln!(\"short read: need {} bytes\", buf.len());\n    }\n    Err(e) => return Err(e),\n    Ok(()) => (),\n}","preventionTips":["Size buffers from the source length, not hardcoded constants","Re-verify downloaded/copied index files (checksums, size checks)","Double-check slice ranges when building OwnedBytes::slice calls","In tests, build fixtures with actual serialization output"],"tags":["io","eof","deserialization","ownedbytes"],"backgroundTag":"unexpected-eof-short-read","analyzedSha":"b5d8deb80c26924e6b007a5b1a7630f35ca64de4","analyzedAt":"2026-09-05T13:20:51.521Z","contentChangedAt":"2026-09-05T13:20:51.521Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}