python/cpython · error · ArgumentTypeError

can't open '%(filename)s': %(error)s

Error message

can't open '%(filename)s': %(error)s

What it means

argparse.FileType.__call__ opens the given path with the configured mode/encoding; any OSError from open() (missing file, permission denied, IsADirectoryError) is wrapped in ArgumentTypeError with the filename and the underlying error. Note it is raised during parsing, so an unopenable file aborts argument parsing with argparse's standard error exit unless handled.

Source

Thrown at Lib/argparse.py:1515

    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)

# ===========================
# Optional and Positional Parsing
# ===========================

class Namespace(_AttributeHolder):
    """Simple object for storing attributes.

    Implements equality by attribute names and values, and provides a simple
    string representation.

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Pre-create the output directory (e.g. Path(p).parent.mkdir(parents=True, exist_ok=True)) — FileType will not do it for you.
  2. Verify the file exists/readability before parsing when a better error message matters: a custom type function that returns a path instead of an open file.
  3. Replace FileType with type=str and open the file yourself in a try/except OSError, so you control the error handling and file lifetime.

Example fix

# before
parser.add_argument('--out', type=argparse.FileType('w'))
parser.parse_args(['--out', 'newdir/out.txt'])  # ArgumentTypeError: can't open ... No such file or directory

# after
parser.add_argument('--out', type=str)
args = parser.parse_args()
Path(args.out).parent.mkdir(parents=True, exist_ok=True)
with open(args.out, 'w') as f: ...
Defensive patterns

Strategy: try-catch

Validate before calling

from pathlib import Path

def input_file_ok(path: str) -> bool:
    p = Path(path)
    return p.is_file() and p.stat().st_size >= 0  # exists and readable-ish

Try / catch

from argparse import ArgumentTypeError

try:
    args = parser.parse_args()
except (ArgumentTypeError, SystemExit) as e:
    msg = str(e)
    if "can't open" in msg:
        # show a friendly message and create missing parent dirs if it was output
        raise SystemExit(f'file error: {msg}')
    raise

Prevention

When it happens

Trigger: add_argument('--out', type=argparse.FileType('w')) and passing a path in a non-existent directory; FileType('r') with a missing file; '-' with a bad mode combination; permission or encoding errors on the target file.

Common situations: Output paths whose parent directories do not exist; scripts run without read permission; users omitting an input file; UTF-8 files read with a non-UTF-8 locale encoding.

Related errors


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