donnemartin/interactive-coding-challenges · error · ValueError
Invalid arg: x1 or x2 out of bounds
Error message
Invalid arg: x1 or x2 out of bounds
What it means
BitsScreen.draw_line raises ValueError when x1 or x2 falls outside the screen: negative, or >= len(screen) * 8 (the total number of bits available). This bounds check runs after the None and empty-input checks.
Source
Thrown at bit_manipulation/draw_line/draw_line_solution.ipynb:166
"## Code"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"class BitsScreen(object):\n",
"\n",
" def draw_line(self, screen, width, x1, x2):\n",
" if None in (screen, width, x1, x2):\n",
" raise TypeError('Invalid argument: None')\n",
" if not screen or not width:\n",
" raise ValueError('Invalid arg: Empty screen or width')\n",
" MAX_BIT_VALUE = len(screen) * 8\n",
" if x1 < 0 or x2 < 0 or x1 >= MAX_BIT_VALUE or x2 >= MAX_BIT_VALUE:\n",
" raise ValueError('Invalid arg: x1 or x2 out of bounds')\n",
" start_bit = x1 % 8\n",
" end_bit = x2 % 8\n",
" first_full_byte = x1 // 8\n",
" if start_bit != 0:\n",
" first_full_byte += 1\n",
" last_full_byte = x2 // 8\n",
" if end_bit != (8 - 1):\n",
" last_full_byte -= 1\n",
" for byte in range(first_full_byte, last_full_byte + 1):\n",
" screen[byte] = int('11111111', base=2)\n",
" start_byte = x1 // 8\n",
" end_byte = x2 // 8\n",
" if start_byte == end_byte:\n",
" left_mask = (1 << (8 - start_bit)) - 1\n",
" right_mask = ~((1 << (8 - end_bit - 1)) - 1)\n",
" mask = left_mask & right_mask\n",
" screen[start_byte] |= mask\n",
" else:\n",View on GitHub (pinned to 358f2cc604)
Solutions
- Clamp coordinates: x = max(0, min(x, len(screen) * 8 - 1))
- Fix off-by-one: use x2 = width - 1, not width
- Verify coordinate space (bits, not bytes/pixels) matches the API expectation
Example fix
# before bits.draw_line(screen, 16, 0, 16) # 2-byte screen, 16 is out of bounds # after bits.draw_line(screen, 16, 0, 15)
Defensive patterns
Strategy: validation
Validate before calling
max_bit = len(screen) * 8
x1, x2 = max(0, x1), max(0, x2)
if x1 >= max_bit or x2 >= max_bit:
raise ValueError(f'coordinates must be < {max_bit}')
bits_screen.draw_line(screen, width, x1, x2) Type guard
def in_bounds(screen, x) -> bool:
return 0 <= x < len(screen) * 8 Try / catch
try:
bits_screen.draw_line(screen, width, x1, x2)
except ValueError as e:
if 'out of bounds' in str(e):
x2 = min(x2, len(screen) * 8 - 1)
bits_screen.draw_line(screen, width, x1, x2)
else:
raise Prevention
- Remember x1/x2 are bit coordinates capped at len(screen)*8 - 1
- End ranges at width-1, not width
- Centralize coordinate clamping in one helper before any draw call
When it happens
Trigger: draw_line(screen, 8, -1, 4), or draw_line(screen, 8, 0, 8) on a 1-byte screen where MAX_BIT_VALUE is 8 and x2 == 8; also passing pixel coordinates where the code expects bit coordinates.
Common situations: Confusing width with total bit capacity, off-by-one at the right edge (x2 == MAX_BIT_VALUE instead of MAX_BIT_VALUE - 1), or reusing coordinates from a larger screen on a smaller buffer.
Related errors
- Invalid arg: Empty screen or width
- Invalid argument: None
- num cannot be 0 or negative
- Index cannot be negative
- root must have at least one child
AI-assisted analysis of donnemartin/interactive-coding-challenges@358f2cc604 (2026-08-28).
Data as JSON: /api/errors/23de27303bd729c2.
Report an issue: GitHub.