{"record":{"id":"74913caedc5d2431","repo":"python/cpython","slug":"invalid-choice-value-r-maybe-you-meant-close","errorCode":null,"errorMessage":"invalid choice: %(value)r, maybe you meant %(closest)r? (choose from %(choices)s)","messagePattern":"invalid choice: %\\(value\\)r, maybe you meant %\\(closest\\)r\\? \\(choose from (.+?)\\)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"Lib/argparse.py","lineNumber":2838,"sourceCode":"            return\n\n        if isinstance(choices, str):\n            choices = iter(choices)\n\n        if value not in choices:\n            args = {'value': str(value),\n                    'choices': ', '.join(repr(str(choice)) for choice in action.choices)}\n            msg = _('invalid choice: %(value)r (choose from %(choices)s)')\n\n            if self.suggest_on_error and isinstance(value, str):\n                if all(isinstance(choice, str) for choice in action.choices):\n                    suggestions = difflib.get_close_matches(value, action.choices, 1)\n                    if suggestions:\n                        args['closest'] = suggestions[0]\n                        msg = _('invalid choice: %(value)r, maybe you meant %(closest)r? '\n                                '(choose from %(choices)s)')\n\n            raise ArgumentError(action, msg % args)\n\n    # =======================\n    # Help-formatting methods\n    # =======================\n\n    def format_usage(self, formatter=None):\n        if formatter is None:\n            formatter = self._get_formatter()\n        formatter.add_usage(self.usage, self._actions,\n                            self._mutually_exclusive_groups)\n        return formatter.format_help()\n\n    def format_help(self, formatter=None):\n        if formatter is None:\n            formatter = self._get_formatter()\n\n        # usage\n        formatter.add_usage(self.usage, self._actions,","sourceCodeStart":2820,"sourceCodeEnd":2856,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/argparse.py#L2820-L2856","documentation":"Same invalid-choice check as the plain error, but when the parser was constructed with suggest_on_error=True (new in Python 3.14) and both the value and all choices are strings, argparse runs difflib.get_close_matches and, if a nearest candidate within the cutoff exists, embeds it in the message as 'maybe you meant ...?'. The raise site is identical to the non-suggesting variant in _check_value.","triggerScenarios":"ArgumentParser(suggest_on_error=True) plus add_argument(x, choices=[...strings...]); the user supplies a string within difflib's similarity cutoff of exactly one choice (e.g. 'jsn' for 'json'). Non-string choices or suggest_on_error=False always yield the plain message.","commonSituations":"Human-facing CLIs where typos are common (--colour vs --color style near-misses); enabling the flag to improve UX and then seeing the extended message in captured error output; tests asserting the exact error string breaking after the flag is turned on.","solutions":["Use the suggested choice from the message.","Keep suggest_on_error off (default) if your test suite asserts exact error text.","Normalize case/whitespace via type=str.lower/.strip so near-misses collapse to exact matches."],"exampleFix":"# before\nparser = argparse.ArgumentParser(suggest_on_error=True)\nparser.add_argument('--fmt', choices=['json', 'xml'])\nparser.parse_args(['--fmt', 'jsn'])\n# invalid choice: 'jsn', maybe you meant 'json'? (choose from 'json', 'xml')\n\n# after\nparser.parse_args(['--fmt', 'json'])","handlingStrategy":"validation","validationCode":"def suggest(parser, value, allowed):\n    import difflib\n    m = difflib.get_close_matches(value, [str(c) for c in allowed], 1)\n    return m[0] if m else None\n\n# pre-validate and hint before argparse raises\nhint = suggest(parser, raw_value, choices_list)","typeGuard":null,"tryCatchPattern":"try:\n    args = parser.parse_args(argv)\nexcept argparse.ArgumentError as e:\n    if 'invalid choice' in str(e):\n        print('check the printed choices list; the message may include a suggestion')","preventionTips":["Keep suggest_on_error off in CI/tests that assert exact error strings.","Normalize input (case/whitespace) so suggestions rarely matter.","When you enable suggestions, update user-facing docs to describe the extended message."],"tags":["argparse","cli","choices","suggestions","difflib"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}