{"record":{"id":"d3635d9fca4e62d4","repo":"TheAlgorithms/Go","slug":"nodes-should-not-have-less-than-the-minimum-number","errorCode":null,"errorMessage":"nodes should not have less than the minimum number of keys","messagePattern":"nodes should not have less than the minimum number of keys","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"structure/tree/btree.go","lineNumber":290,"sourceCode":"\t\t\t\t//  A c C\n\t\t\t\t//   /\n\t\t\t\t// a b\n\t\t\t\treplacementKey := left.Max()\n\t\t\t\tnode.keys[i] = replacementKey\n\t\t\t\tleft.Delete(tree, replacementKey)\n\t\t\t} else if right.numKeys > minKeys {\n\t\t\t\t// Replace the key we want to delete with the min key from the right\n\t\t\t\t// subtree. Then delete that key in the right subtree. Mirrors the\n\t\t\t\t// transformation above for replacing from the left subtree.\n\t\t\t\treplacementKey := right.Min()\n\t\t\t\tnode.keys[i] = replacementKey\n\t\t\t\tright.Delete(tree, replacementKey)\n\t\t\t} else {\n\t\t\t\t// Both left and right subtrees have the minimum number of keys. Merge\n\t\t\t\t// the left tree, the deleted key, and the right tree together into the\n\t\t\t\t// left tree. Then recursively delete the key in the left tree.\n\t\t\t\tif left.numKeys != minKeys || right.numKeys != minKeys {\n\t\t\t\t\tpanic(\"nodes should not have less than the minimum number of keys\")\n\t\t\t\t}\n\t\t\t\tnode.Merge(i)\n\t\t\t\tleft.Delete(tree, key)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tif key < node.keys[i] {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Case 3: key may exist in a child node.\n\tchild := node.children[i]\n\tif child.numKeys == minKeys {\n\t\t// Before we recurse into the child node, make sure it has more than\n\t\t// the minimum number of keys.\n\t\tif i > 0 && node.children[i-1].numKeys > minKeys {","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/TheAlgorithms/Go/blob/5ba447ec5ff3d1213de65b92e726ee74c5d5cc19/structure/tree/btree.go#L272-L308","documentation":"During Delete, when both the left and right siblings of the key's child have the minimum number of keys, the code merges them — but if either actually has FEWER than minKeys, the invariant was already broken and the merge would produce an invalid node, so it panics. This indicates earlier corruption or manual key removal.","triggerScenarios":"Calling tree.Delete on a tree whose nodes were previously underflowed (e.g. via direct DeleteIthKey calls or reflection-based mutation); reusing nodes from a tree with a different maxKeys so minKeys does not match.","commonSituations":"Manually pruned nodes in tests; serialization round-trips that dropped keys; mixing trees with different maxKeys parameters.","solutions":["Only mutate the tree through tree.Insert/tree.Delete.","Rebuild the tree from its keys if it may be corrupted: collect keys and re-insert into a fresh BTree.","Verify invariants with root.Verify(tree) before deleting to catch corruption early.","Ensure consistent maxKeys across all nodes and trees."],"exampleFix":"// before\ntree.Delete(k) // panics on corrupted tree\n// after\nkeys := tree.Keys() // snapshot via in-order walk\nfresh := NewBTree[int](tree.maxKeys)\nfor _, k := range keys { fresh.Insert(k) }\nfresh.Delete(k)","handlingStrategy":"validation","validationCode":"func treeHealthy[T constraints.Ordered](t *BTree[T]) (ok bool) {\n    defer func() { ok = recover() == nil }()\n    if t.root != nil { t.root.Verify(t) }\n    return\n}\nif !treeHealthy(tree) { tree = rebuild(tree) }\ntree.Delete(key)","typeGuard":null,"tryCatchPattern":"func safeDelete[T constraints.Ordered](t *BTree[T], k T) {\n    defer func() {\n        if r := recover() != nil; r { _ = r; t2 := rebuild(t); t2.Delete(k); *t = *t2 }\n    }()\n    t.Delete(k)\n}","preventionTips":["Mutate the tree only through Insert/Delete","Rebuild from key snapshot if corruption is suspected","Verify(root) before batch deletes"],"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"}