python/cpython · error · TypeError
invalid mode: %s
Error message
invalid mode: %s
What it means
Raised by FileIO.__init__ when the mode argument is not a str instance ('invalid mode: %s' % (mode,)). This is a TypeError raised before any mode-character validation, so even a plausible mode like b'rb' or a tuple fails here.
Source
Thrown at Lib/_pyio.py:1560
finally:
self._fd = -1
if isinstance(file, float):
raise TypeError('integer argument expected, got float')
if isinstance(file, int):
if isinstance(file, bool):
import warnings
warnings.warn("bool is used as a file descriptor",
RuntimeWarning, stacklevel=2)
file = int(file)
fd = file
if fd < 0:
raise ValueError('negative file descriptor')
else:
fd = -1
if not isinstance(mode, str):
raise TypeError('invalid mode: %s' % (mode,))
if not set(mode) <= set('xrwab+'):
raise ValueError('invalid mode: %s' % (mode,))
if sum(c in 'rwax' for c in mode) != 1 or mode.count('+') > 1:
raise ValueError('Must have exactly one of create/read/write/append '
'mode and at most one plus')
if 'x' in mode:
self._created = True
self._writable = True
flags = os.O_EXCL | os.O_CREAT
elif 'r' in mode:
self._readable = True
flags = 0
elif 'w' in mode:
self._writable = True
self._truncate = True
flags = os.O_CREAT | os.O_TRUNC
elif 'a' in mode:View on GitHub (pinned to bc6749cc3b)
Solutions
- Pass mode as a plain str like 'rb', 'wb', 'r+b'
- Normalize config values: mode = str(mode) if mode is not None else 'r'
- Check for swapped positional arguments (file, mode) in the call
Example fix
# before
f = io.FileIO('data.bin', b'rb') # TypeError: invalid mode: b'rb'
# after
f = io.FileIO('data.bin', 'rb') Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(mode, str):
raise TypeError(f'mode must be str, got {type(mode).__name__}')
f = io.FileIO(path, mode) Type guard
def is_mode_str(m):
return isinstance(m, str) and len(m) > 0 Try / catch
try:
f = io.FileIO(path, mode)
except TypeError as e:
if 'invalid mode' in str(e):
f = io.FileIO(path, str(mode))
else:
raise Prevention
- Keep modes as plain string literals or typed constants
- Coerce config-loaded modes: mode = str(mode).strip()
- Lint for positional-argument swaps when mode comes from a variable
When it happens
Trigger: open(path, b'rb', buffering=0) via io.FileIO; passing mode as None, an enum object, or bytes; a keyword mix-up where a non-string positional argument lands in the mode slot.
Common situations: Config-driven mode values loaded from JSON/YAML as non-strings; mixing bytes and str mode constants in code migrated from Python 2; passing an IntEnum or custom Mode class where a plain string is required.
Related errors
- integer argument expected, got float
- Must have exactly one of create/read/write/append mode and a
- expected integer from opener
- File not open for reading
- File not open for writing
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/d43528eee9a89ad1.
Report an issue: GitHub.