pypa/pip · error · IDNAError
Unsupported error handling "{errors}"
Error message
Unsupported error handling "{errors}" What it means
Raised by idna's Codec.encode (the stateless codec used by str.encode('idna2008')) when the errors parameter is anything other than 'strict'. The IDNA 2008 codec intentionally supports only strict error handling — all encoding failures must surface as IDNAError — so passing 'ignore', 'replace', 'backslashreplace', etc. is rejected immediately.
Source
Thrown at src/pip/_vendor/idna/codec.py:20
from typing import Any, Optional
from .core import IDNAError, _unicode_dots_re, alabel, decode, encode, ulabel
class Codec(codecs.Codec):
"""Stateless IDNA 2008 codec.
Implements the :class:`codecs.Codec` protocol so that the whole-domain
encoder (:func:`idna.encode`) and decoder (:func:`idna.decode`) are
accessible through the standard codec machinery as ``"idna2008"``.
Only the ``"strict"`` error handler is supported; any other handler
raises :exc:`~idna.IDNAError`.
"""
def encode(self, data: str, errors: str = "strict") -> tuple[bytes, int]: # ty: ignore[invalid-method-override]
if errors != "strict":
raise IDNAError(f'Unsupported error handling "{errors}"')
if not data:
return b"", 0
return encode(data), len(data)
def decode(self, data: bytes, errors: str = "strict") -> tuple[str, int]: # ty: ignore[invalid-method-override]
if errors != "strict":
raise IDNAError(f'Unsupported error handling "{errors}"')
if not data:
return "", 0
return decode(data), len(data)
class IncrementalEncoder(codecs.BufferedIncrementalEncoder):
"""Incremental IDNA 2008 encoder.View on GitHub (pinned to f399c37189)
Solutions
- Omit the errors argument (it defaults to 'strict') or explicitly pass errors='strict'.
- If you need lenient handling, validate/normalize the domain before encoding and handle IDNAError yourself.
- Use idna.encode(domain) directly instead of the codec machinery if you need the full API.
Example fix
# before
encoded = 'café.com'.encode('idna2008', errors='ignore') # raises
# after
encoded = 'café.com'.encode('idna2008') # strict by default Defensive patterns
Strategy: validation
Validate before calling
def safe_idna_encode(domain):
return domain.encode('idna2008') # errors defaults to 'strict' Type guard
def is_valid_errors_value(errors: str) -> bool:
return errors == 'strict' Try / catch
from idna.core import IDNAError
try:
encoded = domain.encode('idna2008')
except IDNAError:
encoded = domain.encode('ascii', 'ignore') # fallback for display Prevention
- Never pass errors= to the idna2008 codec — it only supports strict.
- If a framework passes errors generically, register a wrapper that strips it for idna2008.
- Handle IDNAError at the call site for custom fallback behavior.
When it happens
Trigger: Calling 'some-string'.encode('idna2008', errors='ignore') or invoking the codec's encode method with a non-strict errors argument. Also triggered indirectly by libraries that pass a default errors handler to all codecs.
Common situations: A URL-processing library generically passes errors='replace' to all registered codecs; developer assumes idna works like utf-8 with lenient error modes; code copied from a utf-8 example.
Related errors
- Domain too long
- Empty domain
- Empty label
- Got invalid value for load_only - should be one of {}
- Configuration file contains invalid {locale_encoding} charac
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/1398d4068b9ca5f3.
Report an issue: GitHub.