trekhleb/javascript-algorithms · error · Error
Item not found in the tree
Error message
Item not found in the tree
What it means
BinarySearchTreeNode.remove(value) begins with find(value); when find returns null it throws 'Item not found in the tree' rather than returning false. BinarySearchTree.remove just delegates to the root node, so removing any value the tree does not contain — including on an empty tree — raises this error. It is a fail-fast contract: the caller is expected to have verified the value exists.
Source
Thrown at src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js:94
}
/**
* @param {*} value
* @return {boolean}
*/
contains(value) {
return !!this.find(value);
}
/**
* @param {*} value
* @return {boolean}
*/
remove(value) {
const nodeToRemove = this.find(value);
if (!nodeToRemove) {
throw new Error('Item not found in the tree');
}
const { parent } = nodeToRemove;
if (!nodeToRemove.left && !nodeToRemove.right) {
// Node is a leaf and thus has no children.
if (parent) {
// Node has a parent. Just remove the pointer to this node from the parent.
parent.removeChild(nodeToRemove);
} else {
// Node has no parent. Just erase current node value.
nodeToRemove.setValue(undefined);
}
} else if (nodeToRemove.left && nodeToRemove.right) {
// Node has two children.
// Find the next biggest value (minimum value in the right branch)
// and replace current value node with that next biggest value.
const nextBiggerNode = nodeToRemove.right.findMin();View on GitHub (pinned to 85293e3e2b)
Solutions
- Guard the call: if (tree.contains(value)) tree.remove(value); — contains() is the cheap pre-check for exactly this condition.
- If removal is best-effort, wrap remove() in try/catch and treat 'Item not found in the tree' as an idempotent no-op.
- If the value should exist, debug the lookup: print tree.toString(), verify the value's type, and check that the constructor's comparator treats the stored and passed values as equal.
Example fix
// before
bst.remove(42); // throws 'Item not found in the tree' when 42 is absent
// after
if (bst.contains(42)) {
bst.remove(42);
} Defensive patterns
Strategy: validation
Validate before calling
// BinarySearchTree.contains() is the exact pre-check for this throw
function safeRemove(tree, value) {
if (!tree.contains(value)) {
return false;
}
return tree.remove(value);
} Try / catch
try {
tree.remove(value);
} catch (e) {
if (e.message === 'Item not found in the tree') {
return false; // treat as idempotent delete
}
throw e; // never swallow unrelated errors
} Prevention
- Treat remove() as strict: always pair it with contains() or find() when the value's presence is not guaranteed.
- Delete-once patterns: mark ids as processed, or use a Set, so retries do not re-remove.
- Normalize value types at the boundary (Number(), String()) so find() sees the same shape that was inserted.
- When using a custom comparator, unit-test that insert-then-remove round-trips for every value shape you store.
When it happens
Trigger: bst.remove(x) where x was never inserted; removing from an empty tree; deleting the same value twice in a row; removing a value whose type differs from the stored one ('42' vs 42); using a custom nodeValueCompareFunction whose equality branch disagrees with how values were inserted, so find() misses a node that is visually present.
Common situations: Cleanup loops deleting ids that may already be gone; retry or duplicate request handlers calling remove twice; values parsed from JSON where numbers arrive as strings; comparator or config drift between the insert and remove paths.
Related errors
- Can't remove ${value}. Remove method is not implemented yet
- You have to implement heap pair comparison method
- Position is out of allowed range
- Left index can not be greater than right one
AI-assisted analysis of trekhleb/javascript-algorithms@85293e3e2b (2026-08-24).
Data as JSON: /api/errors/ea8caa14580f65ef.
Report an issue: GitHub.