python/cpython · error · ArgumentError

expected argument

Error message

expected %s argument

What it means

Inside _get_values, argparse matches an option's trailing arguments against a regex derived from its nargs pattern; if the pattern cannot match (match is None), it raises ArgumentError with a message keyed to nargs: 'expected one argument' (nargs=None), 'expected at most one argument' (nargs='?'), 'expected at least one argument' (nargs='+'), or 'expected N argument(s)' for integer nargs. It means the option was present but not enough value tokens followed it.

Solutions

  1. Provide the missing value token(s) after the option.
  2. If the value can legitimately be absent, use nargs='?' with a default.
  3. For values starting with '-', use the `--opt=-value` inline form so the value is not mistaken for an option.
  4. For values that look like options (e.g. negative numbers), pass type=int so argparse's negative-number matcher accepts them.

Example fix

# before
parser.add_argument('--tag')
parser.parse_args(['--tag'])  # error: expected one argument

# after
parser.parse_args(['--tag=v1'])  # or ['--tag', 'v1']
Defensive patterns

Strategy: validation

Validate before calling

def option_has_values(argv, parser):
    one_val = {s.split('=')[0] for a in parser._actions if a.nargs is None
               for s in a.option_strings}
    for i, tok in enumerate(argv):
        name = tok.split('=', 1)[0]
        if name in one_val:
            if '=' in tok:
                continue
            if i + 1 >= len(argv) or argv[i + 1].startswith('-'):
                return tok  # --opt with no following value token
    return None

Try / catch

try:
    args = parser.parse_args(argv)
except argparse.ArgumentError as e:
    if 'expected' in str(e) and 'argument' in str(e):
        print('option present but missing its value token(s)')

Prevention

When it happens

Trigger: `--opt` at end of argv with nargs=None and no following value; `--opt --other value` where the next token looks like an option so cannot serve as the value; nargs=3 with only 2 remaining values; nargs='+' with zero non-option tokens left (note: nargs='*' is the one form that never triggers this).

Common situations: Option moved to the end of a generated command line with its value dropped; a value that itself starts with '-' (e.g. negative number or -f) being consumed as an option; shell quoting bugs eating an argument; users assuming `--opt` alone is valid for a one-value option.

Related errors


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

Appendix: source

Thrown at Lib/argparse.py:2555

    def _match_argument(self, action, arg_strings_pattern):
        # match the pattern for this action to the arg strings
        nargs_pattern = self._get_nargs_pattern(action)
        match = _re.match(nargs_pattern, arg_strings_pattern)

        # raise an exception if we weren't able to find a match
        if match is None:
            nargs_errors = {
                None: _('expected one argument'),
                OPTIONAL: _('expected at most one argument'),
                ONE_OR_MORE: _('expected at least one argument'),
            }
            msg = nargs_errors.get(action.nargs)
            if msg is None:
                msg = ngettext('expected %s argument',
                               'expected %s arguments',
                               action.nargs) % action.nargs
            raise ArgumentError(action, msg)

        # return the number of arguments matched
        return len(match.group(1))

    def _match_arguments_partial(self, actions, arg_strings_pattern):
        # progressively shorten the actions list by slicing off the
        # final actions until we find a match
        for i in range(len(actions), 0, -1):
            actions_slice = actions[:i]
            pattern = ''.join([self._get_nargs_pattern(action)
                               for action in actions_slice])
            match = _re.match(pattern, arg_strings_pattern)
            if match is not None:
                result = [len(string) for string in match.groups()]
                if (match.end() < len(arg_strings_pattern)
                    and arg_strings_pattern[match.end()] == 'O'):
                    while result and not result[-1]:
                        del result[-1]

View on GitHub (pinned to bc6749cc3b)