donnemartin/interactive-coding-challenges · error · TypeError

Cannot have a None input

Error message

Cannot have a None input

What it means

Raised by Hanoi.move_disks when any of the src, dest, or buff tower arguments is None. It is an explicit input-validation guard at the top of the public API before the recursive _move_disks helper runs, because the algorithm assumes all three pegs are real stack-like objects. It exists to fail fast with a clear message instead of an opaque AttributeError deep in the recursion.

Source

Thrown at recursion_dynamic/hanoi/hanoi_solution.ipynb:100

   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%run ../../stacks_queues/stack/stack.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Hanoi(object):\n",
    "\n",
    "    def move_disks(self, num_disks, src, dest, buff):\n",
    "        if src is None or dest is None or buff is None:\n",
    "            raise TypeError('Cannot have a None input')\n",
    "        self._move_disks(num_disks, src, dest, buff)\n",
    "\n",
    "    def _move_disks(self, num_disks, src, dest, buff):\n",
    "        if num_disks == 0:\n",
    "            return\n",
    "        self.move_disks(num_disks - 1, src, buff, dest)\n",
    "        dest.push(src.pop())\n",
    "        self.move_disks(num_disks - 1, buff, dest, src)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Unit Test\n",
    "\n"
   ]
  },

View on GitHub (pinned to 358f2cc604)

Solutions

  1. Ensure all three tower arguments are initialized (e.g. dest = Stack(), buff = Stack()) before calling move_disks
  2. If pegs may be absent, default them to empty Stack instances instead of None
  3. Add a caller-side guard: if any peg is None, skip or report the call before invoking move_disks

Example fix

// before
hanoi.move_disks(3, src, None, buff)
// after
buff = Stack()
hanoi.move_disks(3, src, dest, buff)
Defensive patterns

Strategy: validation

Validate before calling

if src is None or dest is None or buff is None:
    raise ValueError('all towers must be provided')
hanoi.move_disks(n, src, dest, buff)

Type guard

def valid_towers(*towers):
    return all(t is not None for t in towers)

Try / catch

try:
    hanoi.move_disks(n, src, dest, buff)
except TypeError as e:
    if 'Cannot have a None input' in str(e):
        # initialize missing towers and retry
        ...

Prevention

When it happens

Trigger: Calling hanoi.move_disks(num_disks, None, dest, buff), or passing any peg as None, e.g. initializing tower objects where one failed to construct. The very first check in move_disks triggers before any recursion.

Common situations: Building the three stacks (source/destination/buffer) from user input or a config where one is missing; refactoring constructors so a peg defaults to None; unmarshalling data where a tower list is absent.

Related errors


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