{"id":"4d02963a6c30165d","repo":"pypa/pip","slug":"unknown-codepoint-adjacent-to-joiner-unot-cp-val","errorCode":null,"errorMessage":"Unknown codepoint adjacent to joiner {_unot(cp_value)} at position {pos + 1} in {label!r}","messagePattern":"Unknown codepoint adjacent to joiner (.+?) at position (.+?) in (.+?)","errorType":"validation","errorClass":"IDNAError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/idna/core.py","lineNumber":365,"sourceCode":"    # Reject on domain length rather than label length so support some UTS 46\n    # use cases, still reducing processing of label contextual rules\n    if not valid_string_length(label, trailing_dot=True):\n        raise IDNAError(\"Label too long\")\n\n    check_nfc(label)\n    check_hyphen_ok(label)\n    check_initial_combiner(label)\n\n    for pos, cp in enumerate(label):\n        cp_value = ord(cp)\n        if intranges_contain(cp_value, idnadata.codepoint_classes[\"PVALID\"]):\n            continue\n        if intranges_contain(cp_value, idnadata.codepoint_classes[\"CONTEXTJ\"]):\n            try:\n                if not valid_contextj(label, pos):\n                    raise InvalidCodepointContext(f\"Joiner {_unot(cp_value)} not allowed at position {pos + 1} in {label!r}\")\n            except ValueError as err:\n                raise IDNAError(\n                    f\"Unknown codepoint adjacent to joiner {_unot(cp_value)} at position {pos + 1} in {label!r}\"\n                ) from err\n        elif intranges_contain(cp_value, idnadata.codepoint_classes[\"CONTEXTO\"]):\n            if not valid_contexto(label, pos):\n                raise InvalidCodepointContext(f\"Codepoint {_unot(cp_value)} not allowed at position {pos + 1} in {label!r}\")\n        else:\n            raise InvalidCodepoint(f\"Codepoint {_unot(cp_value)} at position {pos + 1} of {label!r} not allowed\")\n\n    check_bidi(label)\n\n\ndef alabel(label: str) -> bytes:\n    \"\"\"Convert a single U-label into its A-label form.\n\n    The result is the ASCII-Compatible Encoding (ACE) form per :rfc:`5891`\n    §4: the label is validated, Punycode-encoded, and prefixed with\n    ``xn--``. Pure ASCII labels that are already valid IDNA labels are\n    returned unchanged (as :class:`bytes`).","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/idna/core.py#L347-L383","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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."],"exampleFix":"# before\n# label has U+200D + a newer-Unicode Virama char\nidna.encode(label)  # Unknown codepoint adjacent to joiner\n\n# after\n# upgrade runtime, or pre-filter:\nif any(unicodedata.name(c, None) is None for c in label):\n    raise ValueError('label uses unsupported codepoints for this runtime')\nidna.encode(label)","handlingStrategy":"validation","validationCode":"import unicodedata\ndef runtime_knows_all_chars(label: str) -> bool:\n    return all(unicodedata.name(c, None) is not None for c in label)","typeGuard":"import unicodedata\ndef is_label_runtime_supported(label: str) -> bool:\n    return all(unicodedata.name(c, None) is not None for c in label)","tryCatchPattern":"from idna import IDNAError\ntry:\n    idna.encode(label)\nexcept IDNAError as e:\n    if 'Unknown codepoint adjacent to joiner' in str(e):\n        raise ValueError('runtime Unicode tables too old for this label; upgrade Python') from e\n    raise","preventionTips":["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."],"tags":["idna","contextj","unicode","runtime-version","pip"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}