donnemartin/interactive-coding-challenges · error · ValueError

Invalid arg: Empty screen or width

Error message

Invalid arg: Empty screen or width

What it means

BitsScreen.draw_line raises ValueError('Invalid arg: Empty screen or width') when the screen buffer is empty/falsy or width is 0. Drawing a line requires at least one byte of screen and a positive width, so truthiness is checked before computing MAX_BIT_VALUE.

Source

Thrown at bit_manipulation/draw_line/draw_line_solution.ipynb:163

   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 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",

View on GitHub (pinned to 358f2cc604)

Solutions

  1. Allocate a non-empty screen: screen = bytearray(height_bytes)
  2. Ensure width is a positive multiple related to screen size before calling
  3. Add an early guard that skips drawing when there is nothing to draw

Example fix

# before
screen = bytearray(0)
bits.draw_line(screen, 16, 0, 15)

# after
screen = bytearray(2)  # 16 bits
bits.draw_line(screen, 16, 0, 15)
Defensive patterns

Strategy: validation

Validate before calling

if not screen or not width:
    raise ValueError('screen buffer and width must be non-empty/positive')
bits_screen.draw_line(screen, width, x1, x2)

Type guard

def valid_screen(buf, w) -> bool:
    return bool(buf) and isinstance(w, int) and w > 0

Try / catch

try:
    bits_screen.draw_line(screen, width, x1, x2)
except ValueError as e:
    if 'Empty screen' in str(e):
        screen = bytearray(max(1, width // 8))
        bits_screen.draw_line(screen, width, x1, x2)
    else:
        raise

Prevention

When it happens

Trigger: draw_line(bytearray(), 8, 0, 0) or draw_line(screen, 0, 0, 7) — an empty bytearray or zero width; also passing a screen variable that was never allocated.

Common situations: Allocating the screen buffer conditionally and skipping allocation on some path; computing width from a division/config value that evaluates to 0.

Related errors


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