{"record":{"id":"4a1149e21639a2a9","repo":"python/cpython","slug":"not-allowed-with-argument-s","errorCode":null,"errorMessage":"not allowed with argument %s","messagePattern":"not allowed with argument (.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"Lib/argparse.py","lineNumber":2261,"sourceCode":"\n        # converts arg strings to the appropriate and then takes the action\n        seen_actions = set()\n        seen_non_default_actions = set()\n        warned = set()\n\n        def take_action(action, argument_strings, option_string=None):\n            seen_actions.add(action)\n            argument_values = self._get_values(action, argument_strings)\n\n            # error if this argument is not allowed with other previously\n            # seen arguments\n            if action.option_strings or argument_strings:\n                seen_non_default_actions.add(action)\n                for conflict_action in action_conflicts.get(action, []):\n                    if conflict_action in seen_non_default_actions:\n                        msg = _('not allowed with argument %s')\n                        action_name = _get_action_name(conflict_action)\n                        raise ArgumentError(action, msg % action_name)\n\n            # take the action if we didn't receive a SUPPRESS value\n            # (e.g. from a default)\n            if argument_values is not SUPPRESS:\n                action(self, namespace, argument_values, option_string)\n\n        # function to convert arg_strings into an optional action\n        def consume_optional(start_index):\n\n            # get the optional identified at this index\n            option_tuples = option_string_indices[start_index]\n            # if multiple actions match, the option string was ambiguous\n            if len(option_tuples) > 1:\n                options = ', '.join([option_string\n                    for action, option_string, sep, explicit_arg in option_tuples])\n                args = {'option': arg_strings[start_index], 'matches': options}\n                msg = _('ambiguous option: %(option)s could match %(matches)s')\n                raise ArgumentError(None, msg % args)","sourceCodeStart":2243,"sourceCodeEnd":2279,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/argparse.py#L2243-L2279","documentation":"Raised by argparse when the command line supplies two or more options that belong to the same mutually exclusive group (created with parser.add_mutually_exclusive_group()). During parsing, argparse records every non-default action in seen_non_default_actions; when a later action's conflict list contains one already seen, it raises ArgumentError with the name of the earlier conflicting argument. The parse aborts before any action callback runs.","triggerScenarios":"parser.add_mutually_exclusive_group() registers options A and B; the user passes both A and B (e.g. `prog --json --xml`). Also triggered when one group member gets a value from an explicit `--opt=v` form or an abbreviation that resolves to a group member, and when group members carry non-None defaults that the user overrides explicitly on a line where another member was already given.","commonSituations":"CLI flags that logically exclude each other (--verbose/--quiet, --json/--xml, --input/--stdin); adding a new flag to an existing mutually exclusive group and forgetting the constraint; users combining short aliases like -v and -q in scripts generated by other tools.","solutions":["Pass only one option from the mutually exclusive group on the command line.","If both behaviors are legitimately combinable, move the options out of the mutually exclusive group or put them in separate groups.","Use a single option with choices (e.g. --output-format json|xml) instead of two exclusive flags.","Catch the error programmatically: construct the parser with exit_on_error=False and catch argparse.ArgumentError to emit a custom message."],"exampleFix":"# before\ng = parser.add_mutually_exclusive_group()\ng.add_argument('--json', action='store_true')\ng.add_argument('--xml', action='store_true')\n# `prog --json --xml` -> error: not allowed with argument --json\n\n# after\nparser.add_argument('--output-format', choices=['json', 'xml'], default='json')","handlingStrategy":"try-catch","validationCode":"import sys\n\ndef group_members_conflict(parser, argv):\n    # crude pre-check: count how many option strings from any\n    # mutually exclusive group appear in argv\n    for group in parser._mutually_exclusive_groups:\n        names = {s for a in group._group_actions for s in a.option_strings}\n        hits = [a for a in argv if a.split('=')[0] in names]\n        if len(hits) > 1:\n            return f'conflicting options: {\" \".join(hits)}'\n    return None","typeGuard":null,"tryCatchPattern":"import argparse\n\nparser = argparse.ArgumentParser(exit_on_error=False)\ntry:\n    args = parser.parse_args(argv)\nexcept argparse.ArgumentError as e:\n    # e.argument identifies the offending action\n    print(f'usage error: {e}', file=sys.stderr)\n    sys.exit(2)","preventionTips":["Model either/or behavior with choices on a single option instead of mutually exclusive groups when conflicts are common.","Document exclusive flags right next to each other in --help via container group titles.","In test suites, assert that each realistic argv combination parses or fails with ArgumentError."],"tags":["argparse","cli","mutually-exclusive","argument-conflict"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}