pypa/pip · error · IDNABidiError
First codepoint in label {label!r} must be directionality L,
Error message
First codepoint in label {label!r} must be directionality L, R or AL What it means
IDNABidiError from check_bidi Bidi Rule 1: the first codepoint of a label under Bidi scrutiny must have bidirectional category L (left-to-right), R, or AL (Arabic letter). Any other leading category (e.g. ET, ON, NSM, EN) is rejected because RFC 5893 requires a strong directional start.
Source
Thrown at src/pip/_vendor/idna/core.py:136
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)
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:View on GitHub (pinned to d7d0d0a394)
Solutions
- Restructure the label so a strong L/R/AL letter is first (move digits/punctuation after the first letter).
- Strip leading punctuation/digits from user input before IDNA encoding.
- Split into multiple labels so each starts with a valid directional character.
Example fix
# before
idna.encode('1-العرب') # First codepoint must be L, R or AL
# after
idna.encode('العرب-1') Defensive patterns
Strategy: validation
Validate before calling
import unicodedata
_VALID_FIRST_BIDI = {'L', 'R', 'AL'}
def has_valid_first_bidi(label: str) -> bool:
return bool(label) and unicodedata.bidirectional(label[0]) in _VALID_FIRST_BIDI Type guard
import unicodedata
def is_strong_directional_start(label: str) -> bool:
return bool(label) and unicodedata.bidirectional(label[0]) in {'L', 'R', 'AL'} Try / catch
from idna import IDNABidiError
try:
idna.check_bidi(label)
except IDNABidiError as e:
if 'First codepoint' in str(e):
label = label.lstrip('0123456789-,.;') # trim weak leading chars
else:
raise Prevention
- Slugify routines should ensure a leading letter rather than a digit/punct.
- Validate the first character's bidi class before encoding.
- Avoid prefixing RTL labels with ASCII digits or punctuation.
When it happens
Trigger: A label starting with a digit, punctuation, combining mark, or European number while the label also contains RTL characters (forcing the Bidi check). Example: '1اabc' or ',بtest'.
Common situations: Auto-generated slugs that prefix Arabic/Hebrew words with ASCII digits or punctuation; user handles or subdomains beginning with a number followed by RTL text; data migration that prepended a marker character to existing IDN names.
Related errors
- Unknown directionality in label {label!r} at position {idx}
- 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-
- Label ends with illegal codepoint directionality
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/f82a6562df4dcfe1.json.
Report an issue: GitHub.