{"id":"71ff35bc56044773","repo":"pypa/pip","slug":"no-such-group","errorCode":null,"errorMessage":"No such group","messagePattern":"No such group","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pygments/lexer.py","lineNumber":377,"sourceCode":"\nclass _PseudoMatch:\n    \"\"\"\n    A pseudo match object constructed from a string.\n    \"\"\"\n\n    def __init__(self, start, text):\n        self._text = text\n        self._start = start\n\n    def start(self, arg=None):\n        return self._start\n\n    def end(self, arg=None):\n        return self._start + len(self._text)\n\n    def group(self, arg=None):\n        if arg:\n            raise IndexError('No such group')\n        return self._text\n\n    def groups(self):\n        return (self._text,)\n\n    def groupdict(self):\n        return {}\n\n\ndef bygroups(*args):\n    \"\"\"\n    Callback that yields multiple actions for each group in the match.\n    \"\"\"\n    def callback(lexer, match, ctx=None):\n        for i, action in enumerate(args):\n            if action is None:\n                continue\n            elif type(action) is _TokenType:","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pygments/lexer.py#L359-L395","documentation":"Raised by _PseudoMatch.group(arg) when a non-None group argument is supplied. _PseudoMatch is a stand-in match object (with a single implicit group 0) used internally when a token rule's action is a bare string rather than a real regex match. Asking it for a numbered/named group that doesn't exist raises IndexError.","triggerScenarios":"A custom lexer rule triggers bygroups or a callback that calls match.group(n) for n>=1, but the rule produced a _PseudoMatch (string action) instead of a real compiled-regex match with capture groups.","commonSituations":"Writing a RegexLexer rule whose bygroups arity exceeds the number of capture groups in the regex; mixing default(...) string token transitions with group access; porting a lexer rule that relied on groups that were later removed.","solutions":["Ensure the regex in the token rule has one capture group per action passed to bygroups.","Avoid calling match.group(n>0) inside callbacks attached to string/default rules.","Test the rule's regex with re.compile and inspect .groups to confirm group count."],"exampleFix":"# before: bygroups expects 2 groups but regex has 1\n('([A-Za-z]+)', bygroups(Name, Name))\n# after: add the second capture group\n('([A-Za-z]+)([A-Za-z]+)', bygroups(Name, Name))","handlingStrategy":"validation","validationCode":"import re\ndef groups_match(regex_str, n_actions):\n    return re.compile(regex_str).groups >= n_actions","typeGuard":null,"tryCatchPattern":"try:\n    lexer.add_filter(my_callback_filter)\nexcept IndexError:\n    # rule/group mismatch; revise token definitions\n    pass","preventionTips":["Count capture groups vs bygroups actions before registering rules.","Keep group access inside callbacks aligned with the rule's regex."],"tags":["pygments","lexer","regex","bygroups"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}