{"record":{"id":"bbe4c2e8d7158903","repo":"GitoxideLabs/gitoxide","slug":"the-matching-node-was-checked-to-be-a-subtree","errorCode":null,"errorMessage":"the matching node was checked to be a subtree","messagePattern":"the matching node was checked to be a subtree","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-note/src/lib.rs","lineNumber":286,"sourceCode":"impl InternalNode {\n    fn get(\n        &mut self,\n        annotated_object_id: &oid,\n        nibble: usize,\n        objects: &impl Find,\n        non_notes: &mut Vec<TreeEntry>,\n    ) -> Result<Option<ObjectId>, Error> {\n        if self.load_matching_subtree(annotated_object_id, nibble, objects, non_notes)? {\n            return self.get(annotated_object_id, nibble, objects, non_notes);\n        }\n\n        let index = nibble_at(annotated_object_id, nibble);\n        let should_load = self.children[index]\n            .as_deref()\n            .is_some_and(|node| matches!(node, Node::Subtree(subtree) if subtree.contains(annotated_object_id)));\n        if should_load {\n            let Node::Subtree(subtree) = *self.children[index].take().expect(\"the matching subtree is present\") else {\n                unreachable!(\"the matching node was checked to be a subtree\")\n            };\n            load_subtree(subtree, self, nibble, objects, non_notes)?;\n            return self.get(annotated_object_id, nibble, objects, non_notes);\n        }\n\n        match self.children[index].as_deref_mut() {\n            Some(Node::Internal(child)) => child.get(annotated_object_id, nibble + 1, objects, non_notes),\n            Some(Node::Note(note)) if note.annotated_object_id == annotated_object_id => Ok(Some(note.note_blob_id)),\n            _ => Ok(None),\n        }\n    }\n\n    fn insert(\n        &mut self,\n        entry: Node,\n        nibble: usize,\n        objects: &impl Find,\n        non_notes: &mut Vec<TreeEntry>,","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-note/src/lib.rs#L268-L304","documentation":"In `gix-note`'s subtree-lookup path, the code double-checks with `matches!` that the child at the nibble index is a `Subtree`, then unwraps and re-checks with an `else unreachable!`. Firing means the same memory location changed between the check and the destructuring — an internal concurrency or aliasing violation.","triggerScenarios":"Not reachable in single-threaded traversal; would only fire if child-slot mutation logic (e.g. `take()` placement or `load_subtree` side effects) changed so the node is no longer a `Subtree` when matched.","commonSituations":"Practically never; appears only if notes-tree loading code is refactored incorrectly.","solutions":["Report upstream if observed, including the notes ref and operation (get/insert/remove).","Upgrade `gix-note`.","If maintaining, fold the check-and-destructure into one match to eliminate the double test."],"exampleFix":"// before\nlet Node::Subtree(subtree) = *self.children[index].take().expect(\"...\") else { unreachable!(\"...\") };\n// after\nlet Some(Node::Subtree(subtree)) = self.children[index].take() else { return Err(message(\"child disappeared during subtree load\")) };","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Internal double-check; isolate note lookups via catch_unwind.","preventionTips":["Keep gix-note versions consistent with gix-object","Exercise notes trees with mixed fanout depths in tests"],"tags":["rust","panic","internal-invariant","notes"],"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-16T04:17:20.429Z"}