pypa/pip · error · IDNAError
Unknown codepoint adjacent to joiner {_unot(cp_value)} at po
Error message
Unknown codepoint adjacent to joiner {_unot(cp_value)} at position {pos + 1} in {label!r} What it means
IDNAError raised by check_label when valid_contextj itself raises ValueError while inspecting the neighbors of a CONTEXTJ joiner. _combining_class throws ValueError('Unknown character in unicodedata') when a codepoint adjacent to the joiner has no name in the running Python's unicodedata database — i.e. it belongs to a newer Unicode version than the runtime knows about.
Source
Thrown at src/pip/_vendor/idna/core.py:365
# Reject on domain length rather than label length so support some UTS 46
# use cases, still reducing processing of label contextual rules
if not valid_string_length(label, trailing_dot=True):
raise IDNAError("Label too long")
check_nfc(label)
check_hyphen_ok(label)
check_initial_combiner(label)
for pos, cp in enumerate(label):
cp_value = ord(cp)
if intranges_contain(cp_value, idnadata.codepoint_classes["PVALID"]):
continue
if intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTJ"]):
try:
if not valid_contextj(label, pos):
raise InvalidCodepointContext(f"Joiner {_unot(cp_value)} not allowed at position {pos + 1} in {label!r}")
except ValueError as err:
raise IDNAError(
f"Unknown codepoint adjacent to joiner {_unot(cp_value)} at position {pos + 1} in {label!r}"
) from err
elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]):
if not valid_contexto(label, pos):
raise InvalidCodepointContext(f"Codepoint {_unot(cp_value)} not allowed at position {pos + 1} in {label!r}")
else:
raise InvalidCodepoint(f"Codepoint {_unot(cp_value)} at position {pos + 1} of {label!r} not allowed")
check_bidi(label)
def alabel(label: str) -> bytes:
"""Convert a single U-label into its A-label form.
The result is the ASCII-Compatible Encoding (ACE) form per :rfc:`5891`
§4: the label is validated, Punycode-encoded, and prefixed with
``xn--``. Pure ASCII labels that are already valid IDNA labels are
returned unchanged (as :class:`bytes`).View on GitHub (pinned to d7d0d0a394)
Solutions
- Upgrade Python to a release built against a newer Unicode version (Unicode tables are baked in at CPython build time).
- Pre-filter labels to reject codepoints the runtime cannot name: skip if not unicodedata.name(chr(cp), None).
- Strip the problematic adjacent character or replace the joiner context with a runtime-supported equivalent.
Example fix
# before
# label has U+200D + a newer-Unicode Virama char
idna.encode(label) # Unknown codepoint adjacent to joiner
# after
# upgrade runtime, or pre-filter:
if any(unicodedata.name(c, None) is None 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_knows_all_chars(label: str) -> bool:
return all(unicodedata.name(c, None) is not None for c in label) Type guard
import unicodedata
def is_label_runtime_supported(label: str) -> bool:
return all(unicodedata.name(c, None) is not None for c in label) Try / catch
from idna import IDNAError
try:
idna.encode(label)
except IDNAError as e:
if 'Unknown codepoint adjacent to joiner' in str(e):
raise ValueError('runtime Unicode tables too old for this label; upgrade Python') from e
raise Prevention
- Run on a recent CPython with up-to-date Unicode tables.
- Pre-filter labels: reject any codepoint with no unicodedata.name.
- Pin your runtime version in CI to one that supports your input scripts.
When it happens
Trigger: A label containing U+200C or U+200D plus an adjacent codepoint introduced in a Unicode version newer than the running CPython's bundled tables (e.g. a new Indic Virama or joining character on an older Python). The original ValueError is chained via 'from err'.
Common situations: Running on an older Python (3.6/3.7) processing modern Indic/Arabic domain data; CI on a distro Python with stale Unicode tables; apps on frozen runtimes receiving user input with recent script additions.
Related errors
- Unknown directionality in label {label!r} at position {idx}
- Joiner {_unot(cp_value)} not allowed at position {pos + 1} i
- First codepoint in label {label!r} must be directionality L,
- Label begins with an illegal combining character
- Label must be in Normalization Form C
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/4d02963a6c30165d.json.
Report an issue: GitHub.