- [x] I've checked [docs](https://rich.readthedocs.io/en/latest/introduction.html) and [closed issues](https://github.com/Textualize/rich/issues?q=is%3Aissue+is%3Aclosed) for possible solutions.
- [x] I can't find my issue in the [FAQ](https://github.com/Textualize/rich/blob/master/FAQ.md).
<!--
WAIT! Is this a feature request?
Rich isn't accepting new features. If it can be implemented in a third-party library, then that is what I recommend.
Rich *may* accept enhancements to existing features, if they don't have a disruptive impact on the API.
If you think your feature is exceptional, then please make your case in a discussion.
-->
**Describe the bug**
With the default padding `(0, 1)`, `width_padding` is `1`. If the available console width is no greater than `width + 1`, this calculation returns `0`. This will result in an error.
This bug might be related to the following code in `rich\columns.py` within rich.
```
def __rich_console__:
...
if self.width is not None:
column_count = (max_width) // (self.width + width_padding)
```
`__rich_console__` then passes `column_count` to `iter_renderables`, which evaluates `item_count % column_count` and raises `ZeroDivisionError`.
**Reproduction**
```python
from io import StringIO
from rich.columns import Columns
from rich.console import Console
console = Console(
file=StringIO(),
width=16,
height=24,
force_terminal=True,
color_system=None,
highlight=False,
)
print("size", console.width, "x", console.height)
console.print(Columns([f"file_{i:02d}.txt" for i in range(8)], width=16))
```
Observed:
```
size 16 x 24
Traceback (most recent call last):
File "/home/test01.py", line 15, in <module>
console.print(Columns([f"file_{i:02d}.txt" for i in range(8)], width=16))
File "/home/rich/rich/console.py", line 1731, in print
extend(render(renderable, render_options))
File "/home/rich/rich/console.py", line 1339, in render
for render_output in iter_render:
File "/home/rich/rich/columns.py", line 145, in __rich_console__
_renderables = [
^
File "/home/rich/rich/columns.py", line 115, in iter_renderables
if item_count % column_count:
~~~~~~~~~~~^~~~~~~~~~~~~~
ZeroDivisionError: integer modulo by zero
```
Same function, zero divisor (optional second case):
```python
console.print(Columns(["alpha", "beta"], width=0, padding=0))
```
```
File "/home/rich/rich/columns.py", line 124, in __rich_console__
column_count = (max_width) // (self.width + width_padding)
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ZeroDivisionError: integer division or modulo by zero
```
**Platform**
- Python version: 3.12.3
- Rich version: 15.0.0 (`9d8f9a37`)
- Linux x86_64
I took a look at this and reproduced the crash with a test case.
When `max_width <= self.width + width_padding` (or with `width=0, padding=0`), `column_count` in `rich/columns.py` evaluates to `0`, causing the `ZeroDivisionError` when iterating.
Guarding `column_count` with `max(1, ...)` resolves the issue cleanly:
```python
column_count = (
max(1, max_width // (self.width + width_padding))
if (self.width + width_padding) > 0
else 1
)
```
I've put together a fix with regression tests on my fork:
- Commit: [eminsk/rich@c9f68f3](https://github.com/eminsk/rich/commit/c9f68f339457092728cf5ac86264ad3d8571073c)
- Branch: [`fix/columns-zero-division`](https://github.com/eminsk/rich/tree/fix/columns-zero-division)
Since PRs are currently limited to collaborators on this repo, feel free to cherry-pick this directly or let me know if you'd like me to open a PR once permissions allow.
I hit this while using `Columns` with a fixed width and traced it to `rich/columns.py`. Here's a minimal fix — happy to send a proper PR if collaborators would like one (I can't open one due to the repository's collaborator-only pull request policy).
**Root cause:** in `__rich_console__`, when `self.width` is set:
```python
column_count = (max_width) // (self.width + width_padding)
```
If `self.width + width_padding > max_width` (e.g. `Columns(width=10)` on a console of width 10 with the default padding `(0, 1)`), this evaluates to `0`. `iter_renderables` then evaluates `item_count % column_count`, raising `ZeroDivisionError`.
**Fix:** clamp the column count to at least 1, falling back to a single column:
```python
column_count = max(1, max_width // (self.width + width_padding))
```
**Reproduction (rich 15.0.0):**
```python
from io import StringIO
from rich.console import Console
from rich.columns import Columns
console = Console(file=StringIO(), width=10)
console.print(Columns(["a", "b", "c"], width=10)) # ZeroDivisionError
```
After the fix this renders the items stacked in a single column.
Full fix with a regression test (`test_width_narrower_than_console_does_not_crash`, covering `width == console_width`, `width == 0` on a wider console, and `column_first` with an oversized width) is on my fork, built on current `main`:
**https://github.com/TrueFurina/rich/compare/main...TrueFurina:fix/columns-zero-width-fallback**
(`rich/columns.py` +4/-1, `tests/test_columns.py` +11; `pytest tests/test_columns.py` — 2 passed.)
Feel free to cherry-pick or use it as a base if a collaborator picks this up.
Opened a fix on a fork (CreatePullRequest scope blocked for this account against upstream):
https://github.com/Textualize/rich/compare/main...Pitchfork-and-Torch:rich:cook/columns-zerodiv-narrow-width?expand=1
Clamps `column_count` to at least 1 when fixed `width` does not fit (and when `width + padding <= 0`). Includes a regression test for the issue repro.