python/cpython · error · ValueError
can't have read/write/append mode at once
Error message
can't have read/write/append mode at once
What it means
Raised by io.open() as a ValueError when the mode string selects more than one of the base operations create(x)/read(r)/write(w)/append(a). Exactly one base operation is required; '+' adds the complementary direction on top of it.
Source
Thrown at Lib/_pyio.py:219
raise TypeError("invalid buffering: %r" % buffering)
if encoding is not None and not isinstance(encoding, str):
raise TypeError("invalid encoding: %r" % encoding)
if errors is not None and not isinstance(errors, str):
raise TypeError("invalid errors: %r" % errors)
modes = set(mode)
if modes - set("axrwb+t") or len(mode) > len(modes):
raise ValueError("invalid mode: %r" % mode)
creating = "x" in modes
reading = "r" in modes
writing = "w" in modes
appending = "a" in modes
updating = "+" in modes
text = "t" in modes
binary = "b" in modes
if text and binary:
raise ValueError("can't have text and binary mode at once")
if creating + reading + writing + appending > 1:
raise ValueError("can't have read/write/append mode at once")
if not (creating or reading or writing or appending):
raise ValueError("must have exactly one of read/write/append mode")
if binary and encoding is not None:
raise ValueError("binary mode doesn't take an encoding argument")
if binary and errors is not None:
raise ValueError("binary mode doesn't take an errors argument")
if binary and newline is not None:
raise ValueError("binary mode doesn't take a newline argument")
if binary and buffering == 1:
import warnings
warnings.warn("line buffering (buffering=1) isn't supported in binary "
"mode, the default buffer size will be used",
RuntimeWarning, 2)
raw = FileIO(file,
(creating and "x" or "") +
(reading and "r" or "") +
(writing and "w" or "") +
(appending and "a" or "") +View on GitHub (pinned to bc6749cc3b)
Solutions
- Use 'r+' for read/write without truncation, 'w+' for read/write with truncation, 'a+' for append+read.
- Map boolean flag pairs to complete mode strings via a lookup table instead of concatenating letters.
- Reject conflicting config flags (read and write both set without an explicit mode) at config-validation time.
Example fix
// before
mode = ('r' if read else '') + ('w' if write else '') # 'rw'
open(path, mode)
// after
if read and write:
mode = 'r+' # or 'w+' if truncation desired
elif write:
mode = 'r' if read else 'w'
else:
mode = 'w' if write else 'r'
# simpler: choose from {'r','w','a','r+','w+','a+'} directly Defensive patterns
Strategy: validation
Validate before calling
BASE_MODES = {'r','w','a','x','r+','w+','a+','x+','rb','wb','ab','xb','r+b','w+b','a+b','x+b'}
def pick_mode(read: bool, write: bool, binary: bool, truncate: bool) -> str:
if read and write:
base = 'w+' if truncate else 'r+'
elif write:
base = 'w'
elif read:
base = 'r'
else:
raise ValueError('need read or write')
return base + ('b' if binary else '') Type guard
def one_base_op(mode: str) -> bool:
return len(set(mode) & {'r','w','a','x'}) == 1 Prevention
- Map (read, write) flag pairs to complete mode strings via a table instead of letter concatenation.
- Remember '+' is the read/write combiner; 'rw'/'wa' are never valid.
- Validate config-exposed mode strings against a whitelist.
When it happens
Trigger: open('f', 'rw') — but note 'rw' usually trips the duplicate-character check (166) first; reachable forms are 'ra', 'rx', 'wa', 'wx', 'ax', and combinations like 'rw+'. Users typically intend 'r+' or 'w+'.
Common situations: Programmatic mode composition that ORs independent read and write booleans into concatenated letters; porting C-style 'rw' fopen modes; config schemas that expose separate read:true and write:true flags mapped naively to mode letters.
Related errors
- can't have text and binary mode at once
- must have exactly one of read/write/append mode
- unknown mode: %r
- invalid mode: %r
- binary mode doesn't take an encoding argument
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/33600a1379dd9fb7.
Report an issue: GitHub.