ZeroDivisionError parsing pixel mouse events when terminal pixel size is (0, 0)
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:
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_ratioFor 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
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:
python mre.pyActual 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 zeroThis 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:
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_ratioAlternatively, 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
-> ZeroDivisionErrorThe 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, andZeroDivisionError, and did not find a duplicate. - The minimal reproduction below runs without modification.
- The issue reproduces on a recent Textual release.
Source: Textualize/textual