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

  1. 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
  2. Build modes from a validated choice, not string concatenation: mode in ('rb','wb','ab','xb','r+b','w+b','a+b','x+b')
  3. 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

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


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