python/cpython · error · ValueError
Must have exactly one of create/read/write/append mode and a
Error message
Must have exactly one of create/read/write/append mode and at most one plus
What it means
Raised by FileIO.__init__ when mode does not contain exactly one of the create/read/write/append characters ('r','w','a','x') or contains more than one '+'. After charset validation, the constructor requires sum(c in 'rwax' for c in mode) == 1 and mode.count('+') <= 1, so combined modes like 'rw', 'wr+', or 'r++' are rejected.
Source
Thrown at Lib/_pyio.py:1564
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:
self._writable = True
self._appending = True
flags = os.O_APPEND | os.O_CREAT
View on GitHub (pinned to bc6749cc3b)
Solutions
- Use exactly one base mode: 'r' to read, 'w' to truncate/write, 'a' to append, 'x' to create-exclusively; add '+' only once (e.g. 'r+b') for read-write
- Build modes from a validated choice, not string concatenation: mode in ('rb','wb','ab','xb','r+b','w+b','a+b','x+b')
- If you need read-write on an existing file, use 'r+b'
Example fix
# before f = io.FileIO(path, 'rw') # ValueError: Must have exactly one of create/read/write/append... # after f = io.FileIO(path, 'r+b') # read-write, no truncate
Defensive patterns
Strategy: validation
Validate before calling
import re
if not re.fullmatch(r'[rwax][b+]{0,2}', mode):
raise ValueError(f'bad FileIO mode {mode!r}: need exactly one of r/w/a/x and at most one +')
f = io.FileIO(path, mode) Type guard
def is_valid_fileio_mode(m):
return (isinstance(m, str) and sum(c in 'rwax' for c in m) == 1
and m.count('+') <= 1 and set(m) <= set('xrwab+')) Try / catch
try:
f = io.FileIO(path, mode)
except ValueError as e:
if 'exactly one' in str(e):
f = io.FileIO(path, 'r+b') # read-write default
else:
raise Prevention
- Remember '+' grants the second direction; 'rw' is never a mode
- Whitelist-validate modes from config against a fixed set
- Use open() for combined buffered use; it applies the same rule early with clearer docs
When it happens
Trigger: io.FileIO(path, 'rw') or io.FileIO(path, 'w+rb') — any mode with two of r/w/a/x, or with '++'; also 'rb+'. typo'd '+' duplication like 'r++'.
Common situations: Developers assuming 'rw' works like C's fopen extensions or other languages; building modes by concatenation (base + '+' + extra) where the base already contained a mode letter; refactoring 'r+b' into 'rb+' incorrectly.
Related errors
- negative file descriptor
- invalid mode: %s
- Cannot use closefd=False with file name
- opener returned {fd}
- File not open for reading
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/56a523647e45f25e.
Report an issue: GitHub.