UnicodeEncodeError
The text has a character the target encoding has no byte for — é in ASCII, € in Latin-1, an emoji in a cp1252 console. Positions are character indexes into the str.
Demo
'hello'.encode('ascii')
Positions count characters, not bytes: the emoji in 'ok 👍' is position 3 even though it is 4 bytes in UTF-8. The character in the message is always an escape — \xe9 for é, \u65e5 for 日, \U0001f44d for the emoji — so the message stays ASCII-safe. In Handle, xmlcharrefreplace gives é for é, ready for HTML or XML.
Constructor
| Name | Type | Required | Description |
|---|---|---|---|
| encoding | str | yes | Codec name as shown in the message, e.g. 'ascii'. Stored in e.encoding. |
| object | str | yes | The whole str being encoded. Stored in e.object. |
| start | int | yes | Index of the first character that cannot be encoded. |
| end | int | yes | Index just after the last one. end - start == 1 shows the character itself in the message; a longer range shows "characters in position S-E". |
| reason | str | yes | Why encoding failed, e.g. 'ordinal not in range(128)'. |
Attributes
| Attribute | Type | Meaning |
|---|---|---|
| encoding | str | The codec that failed: 'ascii', 'latin-1', 'utf-8', or 'charmap' for table codecs such as cp1252. |
| object | str | The complete str that was being encoded. |
| start | int | Character index of the first unencodable character. object[start:end] is the offending text. |
| end | int | Character index just past the unencodable run. |
| reason | str | 'ordinal not in range(128)' (ascii), 'ordinal not in range(256)' (latin-1), 'character maps to <undefined>' (charmap), 'surrogates not allowed' (utf-8). |
| args | tuple | All five constructor arguments, in order. |
Common patterns
with open('report.txt', 'w', encoding='utf-8') as f: f.write(text)
import sys sys.stdout.reconfigure(errors='backslashreplace') print('ok 👍')
import unicodedata def ascii_fold(s): return unicodedata.normalize('NFKD', s).encode('ascii', 'ignore').decode('ascii')
try: data = name.encode('latin-1') except UnicodeEncodeError as e: bad = e.object[e.start:e.end] raise ValueError(f'unsupported characters {bad!r} at {e.start}') from e
Examples
Pitfalls
with open('out.txt', 'w', encoding='ascii') as f: f.write('Zoë')
with open('out.txt', 'w', encoding='utf-8') as f: n = f.write('Zoë') n
'Zoë'.encode('ascii', 'ignore')
import unicodedata unicodedata.normalize('NFKD', 'Zoë').encode('ascii', 'ignore')
text = b'caf\xe9'.decode('utf-8', 'surrogateescape') text.encode('utf-8')
text = b'caf\xe9'.decode('utf-8', 'surrogateescape') text.encode('utf-8', 'surrogateescape')
When to use
- Catch it where text leaves your program for a restricted encoding (legacy protocol, ASCII-only header)
- Use start/end/object to tell the user exactly which characters are not supported
- Raise it from a custom codec (with all five arguments)
- Encoding to ASCII or Latin-1 when UTF-8 is allowed — use 'utf-8' and the error disappears
- errors='ignore' on user-visible text — it silently removes characters
- Catching it around print() — fix the stream encoding instead (PYTHONIOENCODING, -X utf8, reconfigure)
Notes
FAQ
Something encoded your text as ASCII, which only covers code points 0-127. If you called .encode('ascii') yourself, use 'utf-8'. If it came from open(), pass encoding='utf-8'. If it came from print() or logging, the output stream's encoding (sys.stdout.encoding) cannot represent the character; set PYTHONIOENCODING=utf-8 or run python -X utf8.