RustPython/RustPython · error · ArgumentTypeError
can't open '%(filename)s': %(error)s
Error message
can't open '%(filename)s': %(error)s
What it means
When the open() call inside FileType.__call__ raises OSError (missing file, missing directory, permission denied), the error is caught and re-raised as ArgumentTypeError carrying the path and the underlying message. parse_args turns this into a usage message on stderr and SystemExit with status 2, so the program stops before your code runs.
Source
Thrown at Lib/argparse.py:1385
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 aaeab4f754)
Solutions
- Pass a correct, existing (read modes) or writable (write modes) path; create parent directories first.
- Use type=str plus your own open() later, wrapped in try/except, so the error is reportable.
- Pre-validate known paths before parse_args and fail with your own message.
Example fix
# before
parser.add_argument('--out', type=argparse.FileType('w'))
# after
parser.add_argument('--out', type=str)
args = parser.parse_args()
with open(args.out, 'w') as out:
out.write(data) Defensive patterns
Strategy: try-catch
Validate before calling
def readable_file(path):
import os
if not os.path.isfile(path):
raise argparse.ArgumentTypeError('file not found: ' + path)
return path
# use: parser.add_argument('-i', type=readable_file) Try / catch
# keep paths as strings at parse time; open later with explicit handling
try:
stream = open(args.out, 'w')
except OSError as exc:
sys.exit('cannot open output file: ' + str(exc)) Prevention
- Prefer type=str plus an explicit open in code you control; reserve FileType for quick tools.
- Create parent directories with os.makedirs(..., exist_ok=True) before parse.
- Resolve paths against an explicit base directory instead of the ambient working directory.
- Catch SystemExit around parse_args in tests to assert the error message.
When it happens
Trigger: add_argument('-i', type=argparse.FileType('r')) with a nonexistent path; FileType('w') where the parent directory does not exist or is not writable.
Common situations: Relative paths resolved from a different working directory (cron, systemd, containers); permission-denied on protected paths; paths coming from environment variables or upstream services.
Related errors
- argument "-" with mode %r
- {type_func!r} is a FileType class object, instance of it mus
- ENOENT
- invalid nargs value
- .__call__() not defined
AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17).
Data as JSON: /api/errors/f3e0074459a6b5d7.
Report an issue: GitHub.