{"record":{"id":"7632ff1db7bcad49","repo":"TheAlgorithms/Go","slug":"cannot-delete-key-from-node-with-minimum-number-of","errorCode":null,"errorMessage":"cannot delete key from node with minimum number of keys","messagePattern":"cannot delete key from node with minimum number of keys","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"structure/tree/btree.go","lineNumber":342,"sourceCode":"\t\t\t// Take a key from the right sibling. Mirrors the transformation above for taking a key from the left sibling.\n\t\t\tright := node.children[i+1]\n\t\t\tchild.Append(node.keys[i], right.children[0])\n\t\t\tnode.keys[i] = right.keys[0]\n\t\t\tright.children[0] = right.children[1]\n\t\t\tright.DeleteIthKey(0)\n\t\t} else {\n\t\t\tif i == 0 {\n\t\t\t\t// Merge with right sibling\n\t\t\t\tnode.Merge(i)\n\t\t\t} else {\n\t\t\t\t// Merge with left sibling\n\t\t\t\tnode.Merge(i - 1)\n\t\t\t\tchild = node.children[i-1]\n\t\t\t}\n\t\t}\n\t}\n\tif child.numKeys == minKeys {\n\t\tpanic(\"cannot delete key from node with minimum number of keys\")\n\t}\n\tchild.Delete(tree, key)\n}\n\nfunc (tree *BTree[T]) Delete(key T) {\n\tif tree.root == nil {\n\t\treturn\n\t}\n\ttree.root.Delete(tree, key)\n\tif tree.root.numKeys == 0 {\n\t\ttree.root = tree.root.children[0]\n\t}\n}\n","sourceCodeStart":324,"sourceCodeEnd":356,"githubUrl":"https://github.com/TheAlgorithms/Go/blob/5ba447ec5ff3d1213de65b92e726ee74c5d5cc19/structure/tree/btree.go#L324-L356","documentation":"Delete refuses to recurse into a child that is already at the minimum key count, because removing a key from it would underflow the node and there is no planned rebalance at this point. Before recursing, Delete should have borrowed from a sibling or merged; hitting this panic means that descent-time rebalancing was skipped or the node was already underfull.","triggerScenarios":"Calling tree.Delete on a tree with underfull nodes created by direct mutation; a descent path where predecessor/successor borrow branches were not taken (single-child situations) leaving the child at minKeys.","commonSituations":"Custom delete wrappers that call node-level methods first; trees reconstructed from partial data; nodes shared across trees with different maxKeys making minKeys inconsistent.","solutions":["Ensure the tree is built and maintained exclusively via tree.Insert/tree.Delete.","Rebuild the tree (collect and re-insert keys) if nodes may be underfull.","Run root.Verify(tree) before deleting to detect underfull nodes.","Do not mix nodes between trees with different maxKeys."],"exampleFix":"// before\nnode.DeleteIthKey(0) // underflows, later Delete panics\n// after\ntree.Delete(key) // rebalances during descent","handlingStrategy":"validation","validationCode":"func canDeleteFrom[T constraints.Ordered](t *BTree[T]) bool {\n    if t.root == nil { return false }\n    minK := (t.maxKeys - 1) / 2\n    var walk func(n *BTreeNode[T]) bool\n    walk = func(n *BTreeNode[T]) bool {\n        if n != t.root && n.numKeys < minK { return false }\n        for _, c := range n.children[:n.numKeys+1] { if !walk(c) { return false } }\n        return true\n    }\n    return walk(t.root)\n}\nif !canDeleteFrom(tree) { tree = rebuild(tree) }\ntree.Delete(key)","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        tree = rebuildTreeFromKeys(tree)\n    }\n}()","preventionTips":["Avoid manual node-level deletions that underflow nodes","Never share nodes between trees with different maxKeys","Run Verify before delete-heavy workloads"],"tags":["panic","btree","invariant-violation"],"backgroundTag":"btree-invariant-violation","analyzedSha":"5ba447ec5ff3d1213de65b92e726ee74c5d5cc19","analyzedAt":"2026-09-02T21:54:30.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}