donnemartin/interactive-coding-challenges · error · ValueError

end indices must be >= 0

Error message

end indices must be >= 0

What it means

Raised by Array.merge_into when source_end_index or dest_end_index is negative. It is a ValueError thrown after the None check on the arrays, because the method converts them to zero-based indices via index - 1 and walks backwards; a negative end index would produce invalid slicing behavior.

Source

Thrown at sorting_searching/merge_into/merge_into_solution.ipynb:161

   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Array(object):\n",
    "\n",
    "    def merge_into(self, source, dest, source_end_index, dest_end_index):\n",
    "        if source is None or dest is None:\n",
    "            raise TypeError('source or dest cannot be None')\n",
    "        if source_end_index < 0 or dest_end_index < 0:\n",
    "            raise ValueError('end indices must be >= 0')\n",
    "        if not source:\n",
    "            return dest\n",
    "        if not dest:\n",
    "            return source\n",
    "        source_index = source_end_index - 1\n",
    "        dest_index = dest_end_index - 1\n",
    "        insert_index = source_end_index + dest_end_index - 1\n",
    "        while dest_index >= 0:\n",
    "            if source[source_index] > dest[dest_index]:\n",
    "                source[insert_index] = source[source_index]\n",
    "                source_index -= 1\n",
    "            else:\n",
    "                source[insert_index] = dest[dest_index]\n",
    "                dest_index -= 1\n",
    "            insert_index -= 1\n",
    "        return source"
   ]
  },

View on GitHub (pinned to 358f2cc604)

Solutions

  1. Compute end indices as len(list), not len(list) - 1 (the method subtracts 1 internally)
  2. Skip merging when either list is empty instead of computing -1
  3. Validate indices >= 0 at the call site before invoking

Example fix

// before
arr.merge_into(src, dest, len(src) - 1, len(dest))
// after
arr.merge_into(src, dest, len(src), len(dest))
Defensive patterns

Strategy: validation

Validate before calling

if source_end_index < 0 or dest_end_index < 0:
    return dest
arr.merge_into(source, dest, source_end_index, dest_end_index)

Type guard

def valid_indices(i, j):
    return isinstance(i, int) and isinstance(j, int) and i >= 0 and j >= 0

Try / catch

try:
    arr.merge_into(src, dest, i, j)
except ValueError as e:
    if 'end indices' in str(e):
        # recompute with len() instead of len()-1
        ...

Prevention

When it happens

Trigger: Calling merge_into(source, dest, -1, 5) or any call where either end index is < 0. Commonly happens when an end index is computed as len(empty_list) - 1 = -1.

Common situations: Passing len(x) - 1 where x is empty; off-by-one arithmetic on sizes; indices derived from user-supplied lengths that were not validated as non-negative.

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/4462a4d0d3a401d6. Report an issue: GitHub.