python/cpython · error · ArgumentError

unrecognized arguments: %s

Error message

unrecognized arguments: %s

What it means

parse_args() calls parse_known_args() and refuses leftover arguments: if anything in argv remains unmatched, it raises ArgumentError('unrecognized arguments: ...') (or calls parser.error() and exits when exit_on_error is True, the default). It means the command line contains options/positionals the parser has no definition for.

Source

Thrown at Lib/argparse.py:2157

                if action.option_strings]

    def _get_positional_actions(self):
        return [action
                for action in self._actions
                if not action.option_strings]

    # =====================================
    # Command line argument parsing methods
    # =====================================

    def parse_args(self, args=None, namespace=None):
        args, argv = self.parse_known_args(args, namespace)
        if argv:
            msg = _('unrecognized arguments: %s') % ' '.join(argv)
            if self.exit_on_error:
                self.error(msg)
            else:
                raise ArgumentError(None, msg)
        return args

    def parse_known_args(self, args=None, namespace=None):
        return self._parse_known_args2(args, namespace, intermixed=False)

    def _parse_known_args2(self, args, namespace, intermixed):
        if args is None:
            # args default to the system args
            args = _sys.argv[1:]
        else:
            # make sure that args are mutable
            args = list(args)

        # default Namespace built from parser defaults
        if namespace is None:
            namespace = Namespace()

        # add any action defaults that aren't present

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Add a definition for the argument, or fix the typo in the invocation.
  2. If extra args are expected, use parse_known_args() and handle the remainder yourself.
  3. Collect passthrough args explicitly with add_argument('rest', nargs=argparse.REMAINDER) or parse the args after '--' manually.

Example fix

# before
args = parser.parse_args(['--verbose', '--output', 'x.txt'])
# ArgumentError: unrecognized arguments: --output x.txt  (no --output defined)

# after
parser.add_argument('--output', '-o')
args = parser.parse_args(['--verbose', '--output', 'x.txt'])  # ok
Defensive patterns

Strategy: fallback

Validate before calling

expected = {'--verbose', '--output'}

def args_recognized(argv: list[str]) -> bool:
    return all(a in expected or not a.startswith('-') for a in argv)

Try / catch

from argparse import ArgumentError

try:
    args = parser.parse_args(argv)
except (ArgumentError, SystemExit):
    args, extra = parser.parse_known_args(argv)
    if extra:
        print(f'ignoring unknown arguments: {extra}')

Prevention

When it happens

Trigger: Typo'd flags (--verbse) when only --verbose is defined; passing values to a flag declared without nargs; extra positionals beyond declared ones; a required option consumed differently under allow_abbrev=False; forwarding unknown passthrough args to a child process without parse_known_args.

Common situations: Wrapper scripts that append extra args; flag renamed between versions while callers still use the old name; abbreviations disabled; arguments intended for another tool after '--' not declared with REMAINDER.

Related errors


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