← All tasks
pythonpypa/twine #1302Not a task: already works

`twine upload --verbose` hangs indefinitely in CI due to Rich bug with BOM character in response

envgap__pypa__twine-1302

01 / FAILURE SIGNATURE

As reported upstream

- [x] I have searched the existing issues (open and closed), and could not find an existing issue
Not a benchmark task.
  • The project already builds and runs before the fix, so there is nothing to repair.

02 / ENVIRONMENT RECIPE

Base commit
ac17a17a9c01c5a2ba10f6ee142cef5aec6f56b0
Manifest
pyproject.toml
Reproduce
Awaiting issue-specific recipe
Run under trace
Awaiting a meaningful runtime command

03 / ORIGINAL ISSUE TEXT

pypa/twine #1302 · read the original issue
### Is there an existing issue for this?

- [x] I have searched the existing issues (open and closed), and could not find an existing issue

### What keywords did you use to search existing issues?

rich
BOM

### What operating system are you using?

Linux

### If you selected 'Other', describe your Operating System here

_No response_

### What version of Python are you running?

```console
$ python --version
Python 3.9.25
```

### How did you install twine? Did you use your operating system's package manager or pip or something else?

```console
$ pip install twine
```

### What version of twine do you have installed (include the complete output)

```console
$ twine --version
twine version 6.2.0 (keyring: 25.7.0, packaging: 26.0, requests: 2.32.5, requests-toolbelt: 1.0.0, urllib3: 2.6.3, id: 1.5.0, importlib-metadata:
8.7.1)
```

### Which package repository are you using?

https://pypi.org/simple/

### Please describe the issue that you are experiencing

`twine upload --verbose` hangs indefinitely in non-TTY environments (e.g. CI pipelines) when the server response body starts with a UTF-8 BOM character (`\ufeff`). This occurs when uploading to Azure DevOps Artifacts with an expired PAT. The process produces no error output and must be manually killed.

The root cause is a bug in Rich < 14.3.3 where `RichHandler` enters an infinite loop in `split_graphemes`/`chop_cells` when word-wrapping text containing a BOM character ([fixed in Rich 14.3.3](https://github.com/Textualize/rich/releases/tag/v14.3.3)). Twine's current dependency of `rich >= 12.0.0` allows the buggy versions.

**Suggested fix:** Bump minimum Rich dependency to `rich >= 14.3.3` in `pyproject.toml`. 

### Please list the steps required to reproduce this behaviour

1. Install twine 6.2.0 with rich 14.3.1 (actually any rich < 14.3.3)
2. Run the following minimal reproduction without a TTY:
```python
import rich.logging, logging
handler = rich.logging.RichHandler(show_time=False, show_path=False)
logger = logging.getLogger("test")
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.info('\ufeff' + 'x' * 400)
print("Done")  # Never reached
```
```bash
python3 mre.py < /dev/null 2>&1 | cat
```
3. Or reproduce via twine directly — upload to a server that returns a BOM-prefixed response (e.g. Azure DevOps Artifacts with an expired PAT):
```bash
twine upload --repository-url https://pkgs.dev.azure.com/<org>/<project>/_packaging/<feed>/pypi/upload -u <user> -p <expired-PAT> --verbose dist/*
```
Without `--verbose`, twine fails correctly. With `--verbose`, it hangs after printing `401 Unauthorized`. 


### Anything else you'd like to mention?

Fixed by upgrading to rich >= 14.3.3 (https://github.com/Textualize/rich/releases/tag/v14.3.3)
Continue on GitHub ↗

04 / LABELS

Labels from the report text only; not yet run

No supported category has been assigned.

Label rules and the text that matched
[]