{"record":{"id":"6094c9d2d5313155","repo":"GitoxideLabs/gitoxide","slug":"never-without-parent","errorCode":null,"errorMessage":"never without parent","messagePattern":"never without parent","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-ref/src/store/file/transaction/commit.rs","lineNumber":135,"sourceCode":"\n        for change in &mut updates {\n            let (reflog_root, relative_name) = self.store.reflog_base_and_relative_path(change.update.name.as_ref());\n            match &change.update.change {\n                Change::Update { .. } => {}\n                Change::Delete { .. } => {\n                    // Reflog deletion happens first in case it fails a ref without log is less terrible than\n                    // a log without a reference.\n                    let reflog_path = reflog_root.join(relative_name);\n                    if let Err(err) = std::fs::remove_file(&reflog_path) {\n                        if err.kind() != std::io::ErrorKind::NotFound {\n                            return Err(Error::DeleteReflog {\n                                source: err,\n                                full_name: change.name(),\n                            });\n                        }\n                    } else {\n                        gix_tempfile::remove_dir::empty_upward_until_boundary(\n                            reflog_path.parent().expect(\"never without parent\"),\n                            &reflog_root,\n                        )\n                        .ok();\n                    }\n                }\n            }\n        }\n\n        if let Some(t) = self.packed_transaction {\n            t.commit().map_err(Error::PackedTransactionCommit)?;\n            // Always refresh ourselves right away to avoid races. We ignore errors as there may be many reasons this fails, and it's not\n            // critical to be done here. In other words, the pack may be refreshed at a later time and then it might work.\n            self.store.force_refresh_packed_buffer().ok();\n        }\n\n        for change in &mut updates {\n            let take_lock_and_delete = match &change.update.change {\n                Change::Update {","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-ref/src/store/file/transaction/commit.rs#L117-L153","documentation":"Panic raised by `.expect(\"never without parent\")` on `reflog_path.parent()` while cleaning up empty reflog directories after a ref deletion. The invariant is that a reflog path always has a parent directory component; a `None` would mean the path was somehow just a root/file name, which cannot happen for valid reflog paths produced by the store.","triggerScenarios":"Committing a ref transaction with deletions whose reflog cleanup path computation yields a parentless path — per the invariant, only from an internal bug in reflog path construction, not normal usage.","commonSituations":"Practically never; possibly exposed by exotic ref names or a bug in reflog path derivation after a gix-ref upgrade.","solutions":["Report the panic to the gitoxide project with the ref name and full stack trace.","Check the deleted ref's name for pathological components that could break path construction.","Update to a gix-ref version where reflog path handling is correct."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// sanity-check the reflog path before deleting refs with reflogs\nlet path = store.reflog_path(name);\nassert!(path.parent().is_some(), \"reflog path must have a parent\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use standard ref names so derived reflog paths are always nested under the reflog root.","Report any panic here with the ref name as a gitoxide bug.","Avoid exotic ref name components in tooling."],"tags":["panic","reflog","internal-invariant","transaction"],"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"}