pypa/pip · error · IDNABidiError
Invalid direction for codepoint at position {idx} in a right
Error message
Invalid direction for codepoint at position {idx} in a right-to-left label What it means
IDNABidiError from check_bidi Bidi Rule 2: in a right-to-left label every codepoint must have a bidi category in the allowed RTL set {R, AL, AN, EN, ES, CS, ET, ON, BN, NSM}. Any codepoint with a category outside that set (e.g. an L-category Latin letter mixed into an Arabic/Hebrew label) is illegal at the given position.
Source
Thrown at src/pip/_vendor/idna/core.py:146
# 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)
if rtl:
# Bidi rule 2
if direction not in _bidi_rtl_allowed:
raise IDNABidiError(f"Invalid direction for codepoint at position {idx} in a right-to-left label")
# Bidi rule 3
if direction in _bidi_rtl_valid_ending:
valid_ending = True
elif direction != "NSM":
valid_ending = False
# Bidi rule 4
if direction in _bidi_rtl_numeric:
if not number_type:
number_type = direction
elif number_type != direction:
raise IDNABidiError("Can not mix numeral types in a right-to-left label")
else:
# Bidi rule 5
if direction not in _bidi_ltr_allowed:
raise IDNABidiError(f"Invalid direction for codepoint at position {idx} in a left-to-right label")
# Bidi rule 6
if direction in _bidi_ltr_valid_ending:
valid_ending = TrueView on GitHub (pinned to d7d0d0a394)
Solutions
- Keep each RTL label script-pure; move Latin fragments to a separate label or replace with a transliteration.
- Audit the offending position reported in the message and remove or remap that codepoint.
- Run a script-consistency check (idnadata.scripts) before IDNA encoding.
Example fix
# before
idna.encode('العxرب') # Invalid direction at position of 'x'
# after
idna.encode('العرب') Defensive patterns
Strategy: validation
Validate before calling
import unicodedata
_RTL_ALLOWED = {'R','AL','AN','EN','ES','CS','ET','ON','BN','NSM'}
def is_pure_rtl_label(label: str) -> bool:
return all(unicodedata.bidirectional(c) in _RTL_ALLOWED for c in label) Type guard
import unicodedata
def is_rtl_label_clean(label: str) -> bool:
return all(unicodedata.bidirectional(c) in {'R','AL','AN','EN','ES','CS','ET','ON','BN','NSM'} for c in label) Try / catch
from idna import IDNABidiError
try:
idna.encode(label)
except IDNABidiError as e:
if 'Invalid direction' in str(e) and 'right-to-left' in str(e):
# remove L-category codepoints and retry, or reject
raise ValueError('mixed scripts in RTL label') from e
raise Prevention
- Keep each RTL (Arabic/Hebrew) label script-pure; do not splice Latin characters into it.
- Audit the position reported in the error message.
- Run a script-consistency check (idnadata.scripts) before encoding.
When it happens
Trigger: Mixing a Latin/different-script L-category character into an otherwise RTL label, e.g. 'العxرب' (Latin 'x' inside Arabic). The position reported is the offending codepoint's index (1-based).
Common situations: Concatenating user-supplied fragments from different scripts into a single DNS label; brand names that splice a Latin trademark into a localized Arabic/Hebrew subdomain; copy-paste errors inserting invisible L-category characters.
Related errors
- First codepoint in label {label!r} must be directionality L,
- Can not mix numeral types in a right-to-left label
- Invalid direction for codepoint at position {idx} in a left-
- Label ends with illegal codepoint directionality
- Unknown directionality in label {label!r} at position {idx}
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/1930cdbd0b76730a.json.
Report an issue: GitHub.