RustPython/RustPython · error · TypeError

dest supplied twice for positional argument, did you mean me

Error message

dest supplied twice for positional argument, did you mean metavar?

What it means

A positional argument's dest comes from the argument name itself, so passing dest= in the same call defines the destination twice. add_argument detects a single non-option string combined with an explicit dest keyword and raises this TypeError, pointing to metavar as the display-only alternative.

Source

Thrown at Lib/argparse.py:1518


    # =======================
    # Adding argument actions
    # =======================

    def add_argument(self, *args, **kwargs):
        """
        add_argument(dest, ..., name=value, ...)
        add_argument(option_string, option_string, ..., name=value, ...)
        """

        # if no positional args are supplied or only one is supplied and
        # it doesn't look like an option string, parse a positional
        # argument
        chars = self.prefix_chars
        if not args or len(args) == 1 and args[0][0] not in chars:
            if args and 'dest' in kwargs:
                raise TypeError('dest supplied twice for positional argument,'
                                ' did you mean metavar?')
            kwargs = self._get_positional_kwargs(*args, **kwargs)

        # otherwise, we're adding an optional argument
        else:
            kwargs = self._get_optional_kwargs(*args, **kwargs)

        # if no default was supplied, use the parser-level default
        if 'default' not in kwargs:
            dest = kwargs['dest']
            if dest in self._defaults:
                kwargs['default'] = self._defaults[dest]
            elif self.argument_default is not None:
                kwargs['default'] = self.argument_default

        # create the action object, and add it to the parser
        action_name = kwargs.get('action')
        action_class = self._pop_action_class(kwargs)

View on GitHub (pinned to aaeab4f754)

Solutions

  1. Rename the positional string itself: add_argument('infile') yields dest='infile' automatically.
  2. Use metavar='input' when only the usage or help display should differ.
  3. Switch to an option string if a custom dest is essential: add_argument('-i', '--infile', dest='infile').

Example fix

# before
parser.add_argument('input', dest='infile')
# after
parser.add_argument('infile', metavar='input')
Defensive patterns

Strategy: validation

Validate before calling

def add_positional(parser, name, **kwargs):
    if 'dest' in kwargs:
        raise TypeError('positional dest comes from its name; use metavar for display')
    return parser.add_argument(name, **kwargs)

Type guard

def is_positional_call(args, prefix_chars):
    return len(args) == 1 and args[0][:1] not in prefix_chars

Prevention

When it happens

Trigger: parser.add_argument('input', dest='infile'); any single argument string that does not start with a prefix character combined with an explicit dest= keyword.

Common situations: Wanting nicer help text while keeping an internal attribute name; copy-paste from an optional-argument definition where dest= is legal.

Related errors


AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17). Data as JSON: /api/errors/c4e385ccceb79472. Report an issue: GitHub.