{"record":{"id":"9a284849ef40b1da","repo":"GitoxideLabs/gitoxide","slug":"name-conversion-infallible","errorCode":null,"errorMessage":"name conversion infallible","messagePattern":"name conversion infallible","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"gix-ref/src/store/file/loose/reference/logiter.rs","lineNumber":22,"sourceCode":"};\n\npub(crate) fn must_be_io_err(err: loose::reflog::Error) -> std::io::Error {\n    match err {\n        loose::reflog::Error::Io(err) => err,\n        loose::reflog::Error::RefnameValidation(_) => unreachable!(\"we are called from a valid ref\"),\n    }\n}\n\nimpl Reference {\n    /// Returns true if a reflog exists in the given `store`.\n    ///\n    /// Please note that this method shouldn't be used to check if a log exists before trying to read it, but instead\n    /// is meant to be the fastest possible way to determine if a log exists or not.\n    /// If the caller needs to know if it's readable, try to read the log instead with a reverse or forward iterator.\n    pub fn log_exists(&self, store: &file::Store) -> bool {\n        store\n            .reflog_exists(self.name.as_ref())\n            .expect(\"name conversion infallible\")\n    }\n    /// Return a reflog reverse iterator for this ref, reading chunks from the back into the fixed buffer `buf`, in the given `store`.\n    ///\n    /// The iterator will traverse log entries from most recent to oldest, reading the underlying file in chunks from the back.\n    /// Return `Ok(None)` if no reflog exists.\n    pub fn log_iter_rev<'b>(\n        &self,\n        store: &file::Store,\n        buf: &'b mut [u8],\n    ) -> std::io::Result<Option<log::iter::Reverse<'b, std::fs::File>>> {\n        store.reflog_iter_rev(self.name.as_ref(), buf).map_err(must_be_io_err)\n    }\n\n    /// Return a reflog forward iterator for this ref and write its file contents into `buf`, in the given `store`.\n    ///\n    /// The iterator will traverse log entries from oldest to newest.\n    /// Return `Ok(None)` if no reflog exists.\n    pub fn log_iter<'a, 'b: 'a>(","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-ref/src/store/file/loose/reference/logiter.rs#L4-L40","documentation":"`Reference::log_exists` calls `Store::reflog_exists`, which returns a Result because the reference name must be converted/validated into a filesystem path. The `expect(\"name conversion infallible\")` asserts this conversion can never fail for a `Reference` that has already been parsed and validated, so a panic here means the internal invariant (an already-validated ref name is always convertible) was broken.","triggerScenarios":"Calling `Reference::log_exists(&store)` on a reference whose name fails path conversion inside `reflog_exists`. With a normal `Reference` obtained from the store this is unreachable; it only fires if the reference was constructed from a name that bypassed validation.","commonSituations":"Effectively never hit by library users; if seen it is almost always a gix-ref bug, or code that hand-built a `Reference` with a malformed/unvalidated name (e.g. containing invalid bytes or path components) rather than one obtained via `store.find`/iteration.","solutions":["Check how the `Reference` value was obtained; only pass references produced/validated by gix-ref into `log_exists`","If the reference was constructed manually, validate the name first (e.g. via `gix_ref::Reference::try_from_path` or name validation APIs)","If it reproduces with store-provided references, report a gix-ref bug including the ref name and repository layout","As a workaround, call `store.reflog_exists(name)` yourself and handle the returned Result instead of the panicking convenience method"],"exampleFix":"// before (manual, unvalidated name)\nlet r = gix_ref::Reference { name: name.try_into()? /* unvalidated */, .. };\nlet exists = r.log_exists(&store);\n// after\nlet exists = store.reflog_exists(r.name.as_ref()).expect(\"why does this fail?\");","handlingStrategy":"validation","validationCode":"fn name_is_valid(ref_name: &gix_ref::PartialNameRef<'_>) -> bool { gix_ref::name::partial::check(ref_name).is_ok() } // validate before constructing a Reference manually","typeGuard":"fn is_store_reference(r: &gix_ref::Reference) -> bool { !r.name.as_bstr().is_empty() && r.name.as_bstr().starts_with(b\"refs/\") }","tryCatchPattern":"// expect() panics cannot be caught in Rust; isolate with catch_unwind if truly needed\nlet exists = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| r.log_exists(&store))).unwrap_or(false);","preventionTips":["Only use Reference values obtained from the store (find/iteration), never hand-built ones","Prefer `store.reflog_exists(name)` and handle the Result over the panicking convenience wrapper","Keep gix-ref updated; these expects encode library invariants","If a panic occurs, capture the ref name and repo layout for a bug report"],"tags":["rust","panic","gix-ref","reflog","internal-invariant"],"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"}