donnemartin/interactive-coding-challenges · error · ValueError

num cannot be 0 or negative

Error message

num cannot be 0 or negative

What it means

Bits.get_next_largest raises ValueError('num cannot be 0 or negative') for num <= 0. The algorithm rearranges set bits of a positive integer to find the next larger number with the same popcount; zero and negatives have no meaningful 'next largest' under that definition.

Source

Thrown at bit_manipulation/get_next/get_next_solution.ipynb:120

   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Bits(object):\n",
    "\n",
    "    def get_next_largest(self, num):\n",
    "        if num is None:\n",
    "            raise TypeError('num cannot be None')\n",
    "        if num <= 0:\n",
    "            raise ValueError('num cannot be 0 or negative')\n",
    "        num_ones = 0\n",
    "        num_zeroes = 0\n",
    "        num_copy = num\n",
    "        # We'll look for index, which is the right-most non-trailing zero\n",
    "        # Count number of zeroes to the right of index\n",
    "        while num_copy != 0 and num_copy & 1 == 0:\n",
    "            num_zeroes += 1\n",
    "            num_copy >>= 1\n",
    "        # Count number of ones to the right of index\n",
    "        while num_copy != 0 and num_copy & 1 == 1:\n",
    "            num_ones += 1\n",
    "            num_copy >>= 1\n",
    "        # Determine index and set the bit\n",
    "        index = num_zeroes + num_ones\n",
    "        num |= 1 << index\n",
    "        # Clear all bits to the right of index\n",
    "        num &= ~((1 << index) - 1)\n",
    "        # Set bits starting from 0\n",

View on GitHub (pinned to 358f2cc604)

Solutions

  1. Guard with if num <= 0 before calling and handle that case separately
  2. Fix the upstream arithmetic that produced a non-positive value
  3. If 0 input is legitimate in your domain, special-case it (answer would be 1-bit numbers)

Example fix

# before
nxt = bits.get_next_largest(count - used)

# after
base = count - used
if base <= 0:
    base = 1
nxt = bits.get_next_largest(base)
Defensive patterns

Strategy: validation

Validate before calling

if num is None or num <= 0:
    raise ValueError('num must be a positive integer')
bits.get_next_largest(num)

Type guard

def is_positive_int(v) -> bool:
    return isinstance(v, int) and not isinstance(v, bool) and v > 0

Try / catch

try:
    nxt = bits.get_next_largest(num)
except ValueError as e:
    if '0 or negative' in str(e):
        nxt = 1  # smallest 1-bit number
    else:
        raise

Prevention

When it happens

Trigger: get_next_largest(0), get_next_largest(-5), or calling with a computed difference/subtraction result that came out zero or negative.

Common situations: Delta computations, array indices that underflow, or unvalidated numeric input from users/config flowing into the call.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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