{"record":{"id":"d4248e04dd5ce2a6","repo":"RustPython/RustPython","slug":"conflicting-subparser-alias-alias","errorCode":null,"errorMessage":"conflicting subparser alias: {alias}","messagePattern":"conflicting subparser alias: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/argparse.py","lineNumber":1261,"sourceCode":"            help=help,\n            metavar=metavar)\n\n    def add_parser(self, name, *, deprecated=False, **kwargs):\n        # set prog from the existing prefix\n        if kwargs.get('prog') is None:\n            kwargs['prog'] = '%s %s' % (self._prog_prefix, name)\n\n        # set color\n        if kwargs.get('color') is None:\n            kwargs['color'] = self._color\n\n        aliases = kwargs.pop('aliases', ())\n\n        if name in self._name_parser_map:\n            raise ValueError(f'conflicting subparser: {name}')\n        for alias in aliases:\n            if alias in self._name_parser_map:\n                raise ValueError(f'conflicting subparser alias: {alias}')\n\n        # create a pseudo-action to hold the choice help\n        if 'help' in kwargs:\n            help = kwargs.pop('help')\n            choice_action = self._ChoicesPseudoAction(name, aliases, help)\n            self._choices_actions.append(choice_action)\n        else:\n            choice_action = None\n\n        # create the parser and add it to the map\n        parser = self._parser_class(**kwargs)\n        if choice_action is not None:\n            parser._check_help(choice_action)\n        self._name_parser_map[name] = parser\n\n        # make parser available under aliases also\n        for alias in aliases:\n            self._name_parser_map[alias] = parser","sourceCodeStart":1243,"sourceCodeEnd":1279,"githubUrl":"https://github.com/RustPython/RustPython/blob/aaeab4f754b4f40efc0c8ab39cf7c4a3c35a8cfd/Lib/argparse.py#L1243-L1279","documentation":"Raised by _SubParsersAction.add_parser when an entry in aliases=[...] already exists in _name_parser_map. Aliases are stored in the same map as real names, so each alias must be unique among all names and aliases of that subparsers group.","triggerScenarios":"subparsers.add_parser('status', aliases=['s']) after subparsers.add_parser('start', aliases=['s']); any alias equal to an existing command name or previously registered alias.","commonSituations":"Auto-derived short aliases (first letters) colliding, e.g. 'serve' and 'status' both mapping to 's'; alias tables merged from several modules.","solutions":["Check each alias against subparsers.choices before registering, and skip or pick another alias on collision.","Derive aliases with a scheme guaranteed unique (e.g. first two letters) or assign short forms only manually."],"exampleFix":"# before\nsubparsers.add_parser('status', aliases=['s'])\n# after\ntaken = set(subparsers.choices)\nalias = 'st' if 's' in taken else 's'\nsubparsers.add_parser('status', aliases=[alias])","handlingStrategy":"validation","validationCode":"def unique_aliases(subparsers, name, candidates):\n    taken = set(subparsers.choices) | {name}\n    return [c for c in candidates if c not in taken]","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat aliases as first-class unique identifiers equal in weight to command names.","Avoid auto-derived short aliases; assign them manually or use a collision-free scheme.","Log the full alias set at CLI construction time for quick audits."],"tags":["argparse","cli","subparsers","aliases","valueerror"],"backgroundTag":"duplicate-subcommand-name","analyzedSha":"aaeab4f754b4f40efc0c8ab39cf7c4a3c35a8cfd","analyzedAt":"2026-08-17T00:37:52.100Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}