python/cpython · error · ArgumentError

not allowed with argument %s

Error message

not allowed with argument %s

What it means

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.

Source

Thrown at Lib/argparse.py:2261

        # converts arg strings to the appropriate and then takes the action
        seen_actions = set()
        seen_non_default_actions = set()
        warned = set()

        def take_action(action, argument_strings, option_string=None):
            seen_actions.add(action)
            argument_values = self._get_values(action, argument_strings)

            # error if this argument is not allowed with other previously
            # seen arguments
            if action.option_strings or argument_strings:
                seen_non_default_actions.add(action)
                for conflict_action in action_conflicts.get(action, []):
                    if conflict_action in seen_non_default_actions:
                        msg = _('not allowed with argument %s')
                        action_name = _get_action_name(conflict_action)
                        raise ArgumentError(action, msg % action_name)

            # take the action if we didn't receive a SUPPRESS value
            # (e.g. from a default)
            if argument_values is not SUPPRESS:
                action(self, namespace, argument_values, option_string)

        # function to convert arg_strings into an optional action
        def consume_optional(start_index):

            # get the optional identified at this index
            option_tuples = option_string_indices[start_index]
            # if multiple actions match, the option string was ambiguous
            if len(option_tuples) > 1:
                options = ', '.join([option_string
                    for action, option_string, sep, explicit_arg in option_tuples])
                args = {'option': arg_strings[start_index], 'matches': options}
                msg = _('ambiguous option: %(option)s could match %(matches)s')
                raise ArgumentError(None, msg % args)

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Pass only one option from the mutually exclusive group on the command line.
  2. If both behaviors are legitimately combinable, move the options out of the mutually exclusive group or put them in separate groups.
  3. Use a single option with choices (e.g. --output-format json|xml) instead of two exclusive flags.
  4. Catch the error programmatically: construct the parser with exit_on_error=False and catch argparse.ArgumentError to emit a custom message.

Example fix

# before
g = parser.add_mutually_exclusive_group()
g.add_argument('--json', action='store_true')
g.add_argument('--xml', action='store_true')
# `prog --json --xml` -> error: not allowed with argument --json

# after
parser.add_argument('--output-format', choices=['json', 'xml'], default='json')
Defensive patterns

Strategy: try-catch

Validate before calling

import sys

def group_members_conflict(parser, argv):
    # crude pre-check: count how many option strings from any
    # mutually exclusive group appear in argv
    for group in parser._mutually_exclusive_groups:
        names = {s for a in group._group_actions for s in a.option_strings}
        hits = [a for a in argv if a.split('=')[0] in names]
        if len(hits) > 1:
            return f'conflicting options: {" ".join(hits)}'
    return None

Try / catch

import argparse

parser = argparse.ArgumentParser(exit_on_error=False)
try:
    args = parser.parse_args(argv)
except argparse.ArgumentError as e:
    # e.argument identifies the offending action
    print(f'usage error: {e}', file=sys.stderr)
    sys.exit(2)

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/4a1149e21639a2a9. Report an issue: GitHub.