{"id":"620eb8f59abf491e","repo":"pypa/pip","slug":"label-ends-with-illegal-codepoint-directionality","errorCode":null,"errorMessage":"Label ends with illegal codepoint directionality","messagePattern":"Label ends with illegal codepoint directionality","errorType":"validation","errorClass":"IDNABidiError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/idna/core.py","lineNumber":169,"sourceCode":"                valid_ending = False\n            # Bidi rule 4\n            if direction in _bidi_rtl_numeric:\n                if not number_type:\n                    number_type = direction\n                elif number_type != direction:\n                    raise IDNABidiError(\"Can not mix numeral types in a right-to-left label\")\n        else:\n            # Bidi rule 5\n            if direction not in _bidi_ltr_allowed:\n                raise IDNABidiError(f\"Invalid direction for codepoint at position {idx} in a left-to-right label\")\n            # Bidi rule 6\n            if direction in _bidi_ltr_valid_ending:\n                valid_ending = True\n            elif direction != \"NSM\":\n                valid_ending = False\n\n    if not valid_ending:\n        raise IDNABidiError(\"Label ends with illegal codepoint directionality\")\n\n    return True\n\n\ndef check_initial_combiner(label: str) -> bool:\n    \"\"\"Reject labels that begin with a combining mark.\n\n    Per :rfc:`5891` §4.2.3.2 a label must not start with a character of\n    Unicode general category ``M`` (Mark).\n\n    :param label: The label to check.\n    :returns: ``True`` if the first character is not a combining mark.\n    :raises IDNAError: If the label begins with a combining character.\n    \"\"\"\n    if unicodedata.category(label[0])[0] == \"M\":\n        raise IDNAError(\"Label begins with an illegal combining character\")\n    return True\n","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/idna/core.py#L151-L187","documentation":"IDNABidiError from check_bidi: after scanning all codepoints, the label must end with a codepoint whose bidi category is a valid ending category (R, AL, EN, AN for RTL; L, EN for LTR). Ending with a separator/neutral like ES, CS, ON (e.g. a hyphen, dot-like char, or punctuation) after the last strong character is rejected.","triggerScenarios":"A label whose final character is punctuation, a separator, or a symbol rather than a letter or number, e.g. 'الع-' (Arabic label ending in hyphen) or 'abc.' (after the trailing-dot split leaves a punctuation tail).","commonSituations":"Hyphens appended by a slugify routine that did not trim the tail; trailing combining marks stripped leaving a NSM-neutral final char; concatenation that leaves a separator dangling at the end.","solutions":["Trim trailing separators, hyphens, and neutral/punctuation characters from the label before encoding.","Ensure the last character is a letter (L/R/AL) or number (EN/AN).","Review your slugify/sanitizer to forbid trailing non-alphanumerics."],"exampleFix":"# before\nidna.encode('العرب-')  # Label ends with illegal codepoint directionality\n\n# after\nidna.encode('العرب')","handlingStrategy":"validation","validationCode":"import unicodedata\ndef has_valid_bidi_ending(label: str) -> bool:\n    if not label:\n        return False\n    d = unicodedata.bidirectional(label[-1])\n    return d in {'L','R','AL','EN','AN'}","typeGuard":"import unicodedata\ndef ends_with_strong_or_number(label: str) -> bool:\n    return bool(label) and unicodedata.bidirectional(label[-1]) in {'L','R','AL','EN','AN'}","tryCatchPattern":"from idna import IDNABidiError\ntry:\n    idna.encode(label)\nexcept IDNABidiError as e:\n    if 'ends with illegal' in str(e):\n        label = label.rstrip('-­.,;:_/')  # trim trailing neutrals\n    else:\n        raise","preventionTips":["Trim trailing separators, hyphens, and neutral/punctuation characters before encoding.","Ensure the last character is a letter or number.","Slugify routines must strip trailing non-alphanumerics."],"tags":["idna","bidi","rfc5893","pip"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}