python/cpython · error · ValueError

unknown mode: %r

Error message

unknown mode: %r

What it means

Raised by io.open() as a ValueError ('unknown mode') when, after building the buffered layer, none of updating/creating/writing/appending/reading matched a buffer class. Earlier validation already requires exactly one of r/w/a/x, so through the public open() this branch is dead code — a defensive assertion against internal inconsistency or patched behavior.

Source

Thrown at Lib/_pyio.py:261

        if buffering == 1 or buffering < 0 and raw._isatty_open_only():
            buffering = -1
            line_buffering = True
        if buffering < 0:
            buffering = max(min(raw._blksize, 8192 * 1024), DEFAULT_BUFFER_SIZE)
        if buffering < 0:
            raise ValueError("invalid buffering size")
        if buffering == 0:
            if binary:
                return result
            raise ValueError("can't have unbuffered text I/O")
        if updating:
            buffer = BufferedRandom(raw, buffering)
        elif creating or writing or appending:
            buffer = BufferedWriter(raw, buffering)
        elif reading:
            buffer = BufferedReader(raw, buffering)
        else:
            raise ValueError("unknown mode: %r" % mode)
        result = buffer
        if binary:
            return result
        encoding = text_encoding(encoding)
        text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering)
        result = text
        text.mode = mode
        return result
    except:
        result.close()
        raise

# Define a default pure-Python implementation for open_code()
# that does not allow hooks. Warn on first use. Defined for tests.
def _open_code_with_warning(path):
    """Opens the provided file with mode ``'rb'``. This function
    should be used when the intent is to treat the contents as
    executable code.

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Use a standard mode string ('r', 'w', 'a', 'x' plus 'b'/'+'/'t'); the normal validators will then guide you.
  2. If you monkeypatched open/_pyio internals, undo the patch or fix the patched flag computation.
  3. In forks of this logic, ensure the buffer-class selection covers the same cases your validation admits.
Defensive patterns

Strategy: validation

Validate before calling

assert mode in {'r','w','a','x'} | {m+'+' for m in 'rwax'} | {m+c for m in 'rwax' for c in ('b','t','+b','+t')}, mode
open(path, mode)

Prevention

When it happens

Trigger: Not reachable via normal open() calls: mode has passed 'must have exactly one of read/write/append mode' by this point. Could only fire with monkeypatched mode flags, a fork of _pyio with modified validation, or direct misuse of the internal code path.

Common situations: Users encounter this string only when grepping the stdlib source or running heavily patched IO stacks (test mocks that stub the mode-flag computation, vendored variants of open()).

Related errors


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