{"record":{"id":"b733356388258f91","repo":"GitoxideLabs/gitoxide","slug":"io-sink-to-never-fail","errorCode":null,"errorMessage":"io::sink() to never fail","messagePattern":"io::sink\\(\\) to never fail","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"gix-pack/src/data/entry/header.rs","lineNumber":120,"sourceCode":"                let mut buf = [0u8; 10];\n                let buf = leb64_encode(*base_distance, &mut buf);\n                out.write_all(buf)?;\n                written += buf.len();\n            }\n            Blob | Tree | Commit | Tag => {}\n        }\n        Ok(written)\n    }\n\n    /// The size of the header in bytes when written in canonical form.\n    ///\n    /// This is the number of bytes [`Self::write_to()`] would emit for `decompressed_size`.\n    /// It does not inspect existing pack bytes and therefore does not preserve non-canonical\n    /// overlong size encodings. Use [`data::Entry::header_size()`] for decoded entries when the\n    /// result has to match the header length present in the pack.\n    pub fn size(&self, decompressed_size: u64) -> usize {\n        self.write_to(decompressed_size, &mut io::sink())\n            .expect(\"io::sink() to never fail\")\n    }\n}\n\n#[inline]\nfn leb64_encode(mut n: u64, buf: &mut [u8; 10]) -> &[u8] {\n    let mut bytes_written = 1;\n    buf[buf.len() - 1] = n as u8 & 0b0111_1111;\n    for out in buf.iter_mut().rev().skip(1) {\n        n >>= 7;\n        if n == 0 {\n            break;\n        }\n        n -= 1;\n        *out = 0b1000_0000 | (n as u8 & 0b0111_1111);\n        bytes_written += 1;\n    }\n    debug_assert_eq!(n, 0, \"BUG: buffer must be large enough to hold a 64 bit integer\");\n    &buf[buf.len() - bytes_written..]","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-pack/src/data/entry/header.rs#L102-L138","documentation":"`Entry::header::size()` computes a pack entry header length by writing to `io::sink()`, which can never fail; any error from `write_to` would indicate a bug, so it `.expect()`s success. Users see this panic only if `write_to` unexpectedly errors, i.e. an internal invariant broken (e.g. a size that cannot be encoded).","triggerScenarios":"Calling `gix_pack::data::entry::header::Entry::size(decompressed_size)` — panics only if the internal LEB64 encoder fails, which should be impossible for valid u64 sizes.","commonSituations":"Practically never hit in the field; encountered only during development, fuzzing, or after library modifications.","solutions":["Report upstream with the decompressed_size value that triggered it","Use `checked_*` / `Entry::header_size()` on decoded entries as a safer alternative","Upgrade to the latest gitoxide version in case the bug is already fixed"],"exampleFix":"// before\nlet sz = header::Entry::Base.size(size); // panics on internal bug\n// after\nlet mut buf = Vec::new();\nlet sz = header.write_to(size, &mut buf)?; // propagate any error instead of panicking","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let size = std::panic::catch_unwind(|| header::Entry::Base.size(decompressed_size)).unwrap_or(0);","preventionTips":["Prefer `data::Entry::header_size()` on decoded entries in production paths","Keep gitoxide updated; this panic indicates a library bug, not user error","File an upstream issue with reproducing input if ever observed"],"tags":["rust","panic","pack","encoding","internal-bug"],"backgroundTag":"internal-invariant-violation","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}