RustPython/RustPython · error · ValueError

argument "-" with mode %r

Error message

argument "-" with mode %r

What it means

FileType maps the special filename '-' to a standard stream: stdin when the mode contains 'r', stdout when it contains 'w', 'a', or 'x'. If the mode contains none of these characters, no stream can be selected, and __call__ raises this ValueError when '-' is passed on the command line for that argument.

Source

Thrown at Lib/argparse.py:1376

            "FileType is deprecated. Simply open files after parsing arguments.",
            category=PendingDeprecationWarning,
            stacklevel=2
        )
        self._mode = mode
        self._bufsize = bufsize
        self._encoding = encoding
        self._errors = errors

    def __call__(self, string):
        # the special argument "-" means sys.std{in,out}
        if string == '-':
            if 'r' in self._mode:
                return _sys.stdin.buffer if 'b' in self._mode else _sys.stdin
            elif any(c in self._mode for c in 'wax'):
                return _sys.stdout.buffer if 'b' in self._mode else _sys.stdout
            else:
                msg = _('argument "-" with mode %r') % self._mode
                raise ValueError(msg)

        # all other arguments are used as file names
        try:
            return open(string, self._mode, self._bufsize, self._encoding,
                        self._errors)
        except OSError as e:
            args = {'filename': string, 'error': e}
            message = _("can't open '%(filename)s': %(error)s")
            raise ArgumentTypeError(message % args)

    def __repr__(self):
        args = self._mode, self._bufsize
        kwargs = [('encoding', self._encoding), ('errors', self._errors)]
        args_str = ', '.join([repr(arg) for arg in args if arg != -1] +
                             ['%s=%r' % (kw, arg) for kw, arg in kwargs
                              if arg is not None])
        return '%s(%s)' % (type(self).__name__, args_str)

View on GitHub (pinned to aaeab4f754)

Solutions

  1. Fix the mode to include a direction character, e.g. 'rb', 'wb', or 'ab'.
  2. If the standard-stream shortcut is not wanted for this argument, reject '-' explicitly with a custom type function instead of FileType.

Example fix

# before
parser.add_argument('--log', type=argparse.FileType('b'))
# after
parser.add_argument('--log', type=argparse.FileType('ab'))
Defensive patterns

Strategy: validation

Validate before calling

def make_file_type(mode, bufsize=-1, encoding=None, errors=None):
    if 'r' not in mode and not any(c in mode for c in 'wax'):
        raise ValueError('mode cannot map dash to a standard stream: ' + repr(mode))
    return argparse.FileType(mode, bufsize, encoding, errors)

Type guard

def supports_dash(mode: str) -> bool:
    return 'r' in mode or any(c in mode for c in 'wax')

Prevention

When it happens

Trigger: argparse.FileType(mode) where the mode has no r/w/a/x — e.g. type=argparse.FileType('b') or an empty mode — combined with the user passing '-'.

Common situations: Mode strings assembled from flags or configuration where the direction letter got dropped; passing a file extension or bare binary flag where a mode string is expected.

Related errors


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