{"id":"c4a534a0eaab640c","repo":"pypa/pip","slug":"invalid-direction-for-codepoint-at-position-idx-c4a534","errorCode":null,"errorMessage":"Invalid direction for codepoint at position {idx} in a left-to-right label","messagePattern":"Invalid direction for codepoint at position (.+?) in a left-to-right label","errorType":"validation","errorClass":"IDNABidiError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/idna/core.py","lineNumber":161,"sourceCode":"        if rtl:\n            # Bidi rule 2\n            if direction not in _bidi_rtl_allowed:\n                raise IDNABidiError(f\"Invalid direction for codepoint at position {idx} in a right-to-left label\")\n            # Bidi rule 3\n            if direction in _bidi_rtl_valid_ending:\n                valid_ending = True\n            elif direction != \"NSM\":\n                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","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/idna/core.py#L143-L179","documentation":"IDNABidiError from check_bidi Bidi Rule 5: in a left-to-right label every codepoint's bidi category must be in the allowed LTR set {L, EN, ES, CS, ET, ON, BN, NSM}. A codepoint outside that set (typically an R/AL/AN RTL character) appearing in a label that started with L makes the label's directionality ambiguous and is rejected at the given position.","triggerScenarios":"An L-started label into which an RTL character (Hebrew, Arabic, AN digit) is inserted, e.g. 'testا'. Triggered when check_ltr=True or when the LTR label is being explicitly bidi-checked; also when the label is being checked because it was passed to check_bidi with check_ltr.","commonSituations":"Usernames or slugs that concatenate ASCII prefixes with localized RTL suffixes; automated domain generators that merge keywords from mixed locales; sanitizer that allows non-ASCII but does not enforce script purity.","solutions":["Keep LTR labels free of R/AL/AN codepoints; move RTL text into its own label.","Pre-filter input with unicodedata.bidirectional and reject any RTL char in an L-started label.","Use idna.encode with uts46=True and std3_rules=True to surface the problem earlier as an InvalidCodepoint."],"exampleFix":"# before\nlabel = 'testا'\nidna.check_bidi(label, check_ltr=True)  # Invalid direction in LTR label\n\n# after\nlabel = 'test'\nidna.check_bidi(label, check_ltr=True)","handlingStrategy":"validation","validationCode":"import unicodedata\n_LTR_ALLOWED = {'L','EN','ES','CS','ET','ON','BN','NSM'}\ndef is_pure_ltr_label(label: str) -> bool:\n    return bool(label) and unicodedata.bidirectional(label[0]) == 'L' and all(unicodedata.bidirectional(c) in _LTR_ALLOWED for c in label)","typeGuard":"import unicodedata\ndef is_ltr_label_clean(label: str) -> bool:\n    return all(unicodedata.bidirectional(c) in {'L','EN','ES','CS','ET','ON','BN','NSM'} for c in label)","tryCatchPattern":"from idna import IDNABidiError\ntry:\n    idna.check_bidi(label, check_ltr=True)\nexcept IDNABidiError as e:\n    if 'left-to-right' in str(e):\n        # remove RTL codepoints or relocate them to a separate label\n        raise ValueError('RTL codepoint in LTR label') from e\n    raise","preventionTips":["Do not mix RTL characters into L-started labels.","Pre-filter with unicodedata.bidirectional and reject RTL chars in LTR labels.","Use idna.encode(uts46=True, std3_rules=True) to surface issues earlier as InvalidCodepoint."],"tags":["idna","bidi","rfc5893","ltr","pip"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}