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_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
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:
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:
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.
The bug
XTermParser.parse_mouse_code()raisesZeroDivisionErrorwhen pixel mousereporting 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; itdoes not mean the terminal has a literal zero-pixel area.
The parser currently checks whether
terminal_pixel_sizeandterminal_sizeare
None, but does not check whether their values are positive:For
terminal_pixel_size == (0, 0),x_ratioandy_ratioare zero. The nextdivision 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
Run with:
python mre.pyActual behavior
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_heightwith a nonzeropixel_widthsimilarly fails aty /= y_ratio.Expected behavior
A zero or otherwise invalid pixel size should be treated as unavailable.
Textual should either:
It should not terminate the input thread.
Possible fix
Validate all dimensions before calculating the ratios:
Alternatively, zero-valued pixel dimensions could be normalized to
Nonewhen 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
Python
Operating System
Terminal
Rich Console options
Additional context
The original failure occurred under Linux and Python 3.14 in
LinuxDriver._run_input_thread():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
parse_mouse_code,x_ratio,terminal_pixel_size, andZeroDivisionError, and did not find a duplicate.