{"record":{"id":"937cd6e24f623da1","repo":"python/cpython","slug":"unknown-parser-parser-name-r-choices-choices","errorCode":null,"errorMessage":"unknown parser %(parser_name)r (choices: %(choices)s)","messagePattern":"unknown parser %\\(parser_name\\)r \\(choices: (.+?)\\)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"Lib/argparse.py","lineNumber":1436,"sourceCode":"    def _get_subactions(self):\n        return self._choices_actions\n\n    def __call__(self, parser, namespace, values, option_string=None):\n        parser_name = values[0]\n        arg_strings = values[1:]\n\n        # set the parser name if requested\n        if self.dest is not SUPPRESS:\n            setattr(namespace, self.dest, parser_name)\n\n        # select the parser\n        try:\n            subparser = self._name_parser_map[parser_name]\n        except KeyError:\n            args = {'parser_name': parser_name,\n                    'choices': ', '.join(self._name_parser_map)}\n            msg = _('unknown parser %(parser_name)r (choices: %(choices)s)') % args\n            raise ArgumentError(self, msg)\n\n        if parser_name in self._deprecated:\n            parser._warning(_(\"command '%(parser_name)s' is deprecated\") %\n                            {'parser_name': parser_name})\n\n        # parse all the remaining options into the namespace\n        # store any unrecognized options on the object, so that the top\n        # level parser can decide what to do with them\n\n        # In case this subparser defines new defaults, we parse them\n        # in a new namespace object and then update the original\n        # namespace for the relevant parts.\n        subnamespace, arg_strings = subparser.parse_known_args(arg_strings, None)\n        for key, value in vars(subnamespace).items():\n            setattr(namespace, key, value)\n\n        if arg_strings:\n            if not hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):","sourceCodeStart":1418,"sourceCodeEnd":1454,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/argparse.py#L1418-L1454","documentation":"_SubParsersAction.__call__ looks up the requested subcommand name in _name_parser_map; a miss raises ArgumentError('unknown parser ...') listing the valid choices. It means the first positional word after the subparsers group does not match any name added via add_subparsers().add_parser(...) (including any aliases).","triggerScenarios":"Running `mytool buld` when only 'build' was registered; dispatching user-typed commands through a subparser; forgetting to register a newly added command; case mismatch (Build vs build); choices generated dynamically and out of sync.","commonSituations":"Typos in CLI invocations; plugin-based CLIs where a plugin failed to register; renaming commands without updating docs/scripts; shells auto-completing stale names.","solutions":["Check the list in the error message and re-run with a registered name (or its alias).","Register the missing command with subparsers.add_parser('name').","Add aliases for renamed commands: add_parser('build', aliases=['b']) so old invocations keep working."],"exampleFix":"# before\nsub = parser.add_subparsers()\nsub.add_parser('build')\nparser.parse_args(['buld'])  # ArgumentError: unknown parser 'buld' (choices: build)\n\n# after\nsub.add_parser('build', aliases=['b'])\nparser.parse_args(['b'])  # ok","handlingStrategy":"try-catch","validationCode":"def known_subcommand(parser, name: str) -> bool:\n    sub = next(a for a in parser._subparsers._group_actions)\n    return name in sub._name_parser_map","typeGuard":null,"tryCatchPattern":"from argparse import ArgumentError\n\ntry:\n    args = parser.parse_args(argv)\nexcept (ArgumentError, SystemExit):\n    # print valid choices and re-raise with context\n    valid = ', '.join(sub._name_parser_map)\n    raise SystemExit(f'unknown command; choose one of: {valid}')","preventionTips":["Register aliases for renamed or abbreviated subcommands","Surface the choices list in your CLI help/usage","Validate dispatched command names against the registered set before invoking argparse"],"tags":["python","argparse","cli","subcommands","user-input"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}