#6706·textual

ZeroDivisionError parsing pixel mouse events when terminal pixel size is (0, 0)

Author: mavik1Created Aug 31, 2026Updated Sep 5, 2026

The bug

XTermParser.parse_mouse_code() raises ZeroDivisionError when pixel mouse reporting is enabled and the terminal's character-cell dimensions are valid, but its pixel dimensions are reported as zero.

On Linux, terminal pixel dimensions may legitimately be reported as zero when the terminal, PTY, multiplexer, or remote session does not provide pixel geometry. A (0, 0) pixel size means that the dimensions are unavailable; it does not mean the terminal has a literal zero-pixel area.

The parser currently checks whether terminal_pixel_size and terminal_size are None, but does not check whether their values are positive:

python
if (
    self.mouse_pixels
    and self.terminal_pixel_size is not None
    and self.terminal_size is not None
):
    pixel_width, pixel_height = self.terminal_pixel_size
    width, height = self.terminal_size
    x_ratio = pixel_width / width
    y_ratio = pixel_height / height
    x /= x_ratio
    y /= y_ratio

For terminal_pixel_size == (0, 0), x_ratio and y_ratio are zero. The next division raises ZeroDivisionError.

In a running application this occurs in Textual's terminal input thread when the user generates a mouse event. It can appear intermittent because the invalid pixel geometry and the mouse input must coincide.

Minimal reproduction

python
from textual._xterm_parser import XTermParser


parser = XTermParser()

# Simulate a terminal that supports pixel mouse reporting and has valid
# character-cell dimensions, but does not provide pixel dimensions.
parser.mouse_pixels = True
parser.terminal_size = (80, 24)
parser.terminal_pixel_size = (0, 0)

# An ordinary SGR mouse-button event at cell/pixel coordinate 1,1.
parser.parse_mouse_code("\x1b[<0;1;1M")

Run with:

bash
python mre.py

Actual behavior

Traceback (most recent call last):
  File "mre.py", line 13, in <module>
    parser.parse_mouse_code("\x1b[<0;1;1M")
  File ".../textual/_xterm_parser.py", line 93, in parse_mouse_code
    x /= x_ratio
ZeroDivisionError: float division by zero

This was reproduced with Textual 8.2.3. The original application report was from Textual 6.8.0 and failed in the same method.

A zero pixel_height with a nonzero pixel_width similarly fails at y /= y_ratio.

Expected behavior

A zero or otherwise invalid pixel size should be treated as unavailable. Textual should either:

  • retain the mouse coordinates without pixel-to-cell conversion, or
  • discard the mouse event if it cannot be interpreted reliably.

It should not terminate the input thread.

Possible fix

Validate all dimensions before calculating the ratios:

python
if (
    self.mouse_pixels
    and self.terminal_pixel_size is not None
    and self.terminal_size is not None
):
    pixel_width, pixel_height = self.terminal_pixel_size
    width, height = self.terminal_size

    if min(pixel_width, pixel_height, width, height) > 0:
        x_ratio = pixel_width / width
        y_ratio = pixel_height / height
        x /= x_ratio
        y /= y_ratio

Alternatively, zero-valued pixel dimensions could be normalized to None when resize events are ingested. A consumer-side validation still seems useful as defensive protection against invalid geometry from any driver or in-band resize report.

Textual Diagnostics

❯ textual diagnose

Textual Diagnostics

Versions

Name Value
Textual 8.2.8
Rich 15.0.0

Python

Name Value
Version 3.14.7
Implementation CPython
Compiler GCC 15.3.0
Executable /home/tom/Projects/rode/workspace/.devenv/state/venv/bin/python3.14

Operating System

Name Value
System Linux
Release 7.2.2
Version #1-NixOS SMP PREEMPT_DYNAMIC Fri Aug 28 06:25:22 UTC 2026

Terminal

Name Value
Terminal Application Alacritty
TERM alacritty
COLORTERM truecolor
FORCE_COLOR Not set
NO_COLOR Not set

Rich Console options

Name Value
size width=139, height=58
legacy_windows False
min_width 1
max_width 139
is_terminal True
encoding utf-8
max_height 58
justify None
overflow None
no_wrap False
highlight None
markup None
height None

Additional context

The original failure occurred under Linux and Python 3.14 in LinuxDriver._run_input_thread():

LinuxDriver.run_input_thread()
  -> XTermParser.feed()
  -> XTermParser.parse()
  -> XTermParser.parse_mouse_code()
  -> x /= x_ratio
  -> ZeroDivisionError

The application itself does not handle mouse events directly. Moving, clicking, or scrolling the mouse is only the immediate trigger; the invalid zero-valued pixel geometry is the underlying cause.

Checklist

  • I searched open and closed issues for parse_mouse_code, x_ratio, terminal_pixel_size, and ZeroDivisionError, and did not find a duplicate.
  • The minimal reproduction below runs without modification.
  • The issue reproduces on a recent Textual release.