pypa/pip · error · IDNABidiError
Unknown directionality in label {label!r} at position {idx}
Error message
Unknown directionality in label {label!r} at position {idx} What it means
Raised inside check_bidi (idna IDNABidiError) when unicodedata.bidirectional(cp) returns an empty string for some codepoint in the label. An empty bidi category means the running Python's unicodedata module predates the Unicode version that defines that codepoint, so idna cannot classify its directionality.
Source
Thrown at src/pip/_vendor/idna/core.py:123
bidirectional categories ``R``, ``AL``, or ``AN``); set ``check_ltr``
to ``True`` to apply it to LTR-only labels as well.
:param label: The label to validate, as a Unicode string.
:param check_ltr: If ``True``, apply the rules even when the label
contains no RTL characters.
:returns: ``True`` if the label satisfies the Bidi Rule.
:raises IDNABidiError: If any of Bidi Rule conditions 1-6 are violated,
or if the directional category of a codepoint cannot be determined.
"""
if len(label) > _max_input_length:
raise IDNAError("Label too long")
# Bidi rules should only be applied if string contains RTL characters
bidi_label = False
for idx, cp in enumerate(label, 1):
direction = unicodedata.bidirectional(cp)
if direction == "":
# String likely comes from a newer version of Unicode
raise IDNABidiError(f"Unknown directionality in label {label!r} at position {idx}")
if direction in _bidi_rtl_categories:
bidi_label = True
if not bidi_label and not check_ltr:
return True
# Bidi rule 1
direction = unicodedata.bidirectional(label[0])
if direction in _bidi_rtl_first:
rtl = True
elif direction == "L":
rtl = False
else:
raise IDNABidiError(f"First codepoint in label {label!r} must be directionality L, R or AL")
valid_ending = False
number_type: Optional[str] = None
for idx, cp in enumerate(label, 1):
direction = unicodedata.bidirectional(cp)View on GitHub (pinned to d7d0d0a394)
Solutions
- Upgrade Python to a release built against a newer Unicode version (CPython embeds the Unicode database at build time).
- Filter or reject input containing codepoints the runtime cannot classify before passing to idna.
- If on a managed runtime, install one bundled with up-to-date Unicode tables (e.g. python3.11+).
Example fix
# before
idna.encode('\U0001FA00somearabic\u0627') # Unknown directionality on old Python
# after
# upgrade runtime, or pre-filter:
if any(unicodedata.bidirectional(c) == '' for c in label):
raise ValueError('label uses unsupported codepoints for this runtime')
idna.encode(label) Defensive patterns
Strategy: validation
Validate before calling
import unicodedata
def runtime_supports_label(label: str) -> bool:
return all(unicodedata.bidirectional(c) != '' for c in label) Type guard
import unicodedata
def is_label_bidi_known(label: str) -> bool:
return all(unicodedata.bidirectional(c) for c in label) Try / catch
from idna import IDNABidiError, encode
try:
encode(label)
except IDNABidiError as e:
if 'Unknown directionality' in str(e):
# runtime Unicode tables are too old for this codepoint
raise ValueError('upgrade Python runtime for this label') from e
raise Prevention
- Run on a recent CPython whose bundled Unicode database covers your input.
- Pre-filter labels: reject any codepoint whose unicodedata.bidirectional is empty.
- Pin your runtime version in CI to one known to support the scripts in your data.
When it happens
Trigger: Encoding a domain containing a codepoint introduced in a Unicode version newer than the one compiled into the running CPython (e.g. a new emoji or historic script on Python built against Unicode 12 when the char is from Unicode 14). The label also must contain an RTL character (or check_ltr=True) for check_bidi to be reached.
Common situations: Running an older Python (e.g. 3.6/3.7) against modern domain data; shipping an app with a frozen/old runtime that lacks recent Unicode tables; CI on an old distro Python processing user-provided internationalized domains.
Related errors
- First codepoint in label {label!r} must be directionality L,
- Unknown codepoint adjacent to joiner {_unot(cp_value)} at po
- Invalid direction for codepoint at position {idx} in a right
- Can not mix numeral types in a right-to-left label
- Invalid direction for codepoint at position {idx} in a left-
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/01594e06ca085451.json.
Report an issue: GitHub.