donnemartin/interactive-coding-challenges · error · TypeError

root cannot be None

Error message

root cannot be None

What it means

Raised by BinaryTree.check_balance() in the check_balance_solution notebook when the tree's root is None. The method is written to treat a missing root as a programming/input error rather than an empty (and trivially balanced) tree, so it refuses to operate. It uses TypeError because the failure is an invalid state passed into the algorithm.

Source

Thrown at graphs_trees/check_balance/check_balance_solution.ipynb:119

    "class BstBalance(Bst):\n",
    "\n",
    "    def _check_balance(self, node):\n",
    "        if node is None:\n",
    "            return 0\n",
    "        left_height = self._check_balance(node.left)\n",
    "        if left_height == -1:\n",
    "            return -1\n",
    "        right_height = self._check_balance(node.right)\n",
    "        if right_height == -1:\n",
    "            return -1\n",
    "        diff = abs(left_height - right_height)\n",
    "        if diff > 1:\n",
    "            return -1\n",
    "        return 1 + max(left_height, right_height)\n",
    "\n",
    "    def check_balance(self):\n",
    "        if self.root is None:\n",
    "            raise TypeError('root cannot be None')\n",
    "        height = self._check_balance(self.root)\n",
    "        return height != -1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Unit Test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",

View on GitHub (pinned to 358f2cc604)

Solutions

  1. Insert at least one node (e.g., tree.insert(1)) before calling check_balance()
  2. If an empty tree is valid in your domain, catch TypeError and treat it as True (an empty tree is balanced)
  3. Modify the class to return True for root is None instead of raising, if you own the code

Example fix

# before
tree = BinaryTree()
tree.check_balance()  # TypeError: root cannot be None

# after
tree = BinaryTree()
tree.insert(1)
tree.check_balance()  # False/True, no error
Defensive patterns

Strategy: validation

Validate before calling

if tree.root is None:
    print('empty tree; nothing to balance-check')
else:
    result = tree.check_balance()

Type guard

def has_root(tree):
    return tree is not None and getattr(tree, 'root', None) is not None

Try / catch

try:
    tree.check_balance()
except TypeError as e:
    if 'root cannot be None' in str(e):
        result = True  # empty tree is balanced by convention
    else:
        raise

Prevention

When it happens

Trigger: Calling check_balance() on a newly constructed BinaryTree (root defaults to None), or on a tree whose root was never inserted/set. Any test that builds the tree but calls check_balance() before inserting nodes hits this immediately.

Common situations: Unit tests that instantiate BinaryTree() and assert check_balance() without seeding a root; refactors that leave a root-assignment line out; copying the solution class into a project where empty trees are expected to be valid input.

Related errors


AI-assisted analysis of donnemartin/interactive-coding-challenges@358f2cc604 (2026-08-28). Data as JSON: /api/errors/976ad9ae83ed3013. Report an issue: GitHub.