{"record":{"id":"75348127f8438b91","repo":"quickwit-oss/tantivy","slug":"unexpectedeof-753481","errorCode":"UnexpectedEof","errorMessage":"File corrupted. The file is smaller than 4 bytes (len={}).","messagePattern":"File corrupted\\. The file is smaller than 4 bytes \\(len=(.+?)\\)\\.","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"src/directory/footer.rs","lineNumber":56,"sourceCode":"        Footer { version, crc }\n    }\n\n    pub(crate) fn crc(&self) -> CrcHashU32 {\n        self.crc\n    }\n    pub(crate) fn append_footer<W: io::Write>(&self, mut write: &mut W) -> io::Result<()> {\n        let mut counting_write = CountingWriter::wrap(&mut write);\n        counting_write.write_all(serde_json::to_string(&self)?.as_ref())?;\n        let footer_payload_len = counting_write.written_bytes();\n        BinarySerializable::serialize(&(footer_payload_len as u32), write)?;\n        BinarySerializable::serialize(&FOOTER_MAGIC_NUMBER, write)?;\n        Ok(())\n    }\n\n    /// Extracts the tantivy Footer from the file and returns the footer and the rest of the file\n    pub fn extract_footer(file: FileSlice) -> io::Result<(Footer, FileSlice)> {\n        if file.len() < 4 {\n            return Err(io::Error::new(\n                io::ErrorKind::UnexpectedEof,\n                format!(\n                    \"File corrupted. The file is smaller than 4 bytes (len={}).\",\n                    file.len()\n                ),\n            ));\n        }\n\n        let footer_metadata_len = <(u32, u32)>::SIZE_IN_BYTES;\n        let (footer_len, footer_magic_byte): (u32, u32) = file\n            .slice_from_end(footer_metadata_len)\n            .read_bytes()?\n            .as_ref()\n            .deserialize()?;\n\n        if footer_magic_byte != FOOTER_MAGIC_NUMBER {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/src/directory/footer.rs#L38-L74","documentation":"Every tantivy segment file ends with a footer whose minimum size is 4 bytes (the footer magic number plus metadata). extract_footer rejects any file smaller than 4 bytes because it cannot possibly contain a valid footer, so the file is treated as corrupted from the start.","triggerScenarios":"Calling extract_footer (or opening an index) on a zero-length or 1-3 byte file: empty file created by a failed write, placeholder/lock files misread as segments, truncated uploads.","commonSituations":"Disk-full or crash during index write leaving empty files; incomplete rsync/scp of the index directory; pointing tantivy at the wrong directory containing stray empty files.","solutions":["Delete or restore the undersized file; it cannot contain valid data","Rebuild the index or restore it from a backup","Check for disk-full or interrupted-write issues on the source filesystem","Compare the directory against commit metadata (meta.json) to identify missing/corrupt segments"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let md = std::fs::metadata(path)?;\nif md.len() < 4 { /* skip / quarantine / restore this file */ }","typeGuard":null,"tryCatchPattern":"match extract_footer(file_slice) {\n    Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {\n        eprintln!(\"file too small for footer, restoring from backup\");\n    }\n    Err(e) => return Err(e),\n    Ok((footer, rest)) => (footer, rest),\n}","preventionTips":["Validate the index directory (all segment sizes > 0) before opening","Ensure completed writes: fsync and atomic rename on publish","Detect disk-full conditions during indexing","Keep verified backups of index directories"],"tags":["io","corrupt-file","footer","eof"],"backgroundTag":"corrupt-index-footer","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"}