python/cpython · error · ValueError

invalid buffering size

Error message

invalid buffering size

What it means

Raised by io.open() as a ValueError when the buffering size is still negative after the default-size resolution step. The code maps buffering<0 (and buffering==1 on a tty) to a computed default from the raw device block size; this raise is a defensive assertion that the computed size is non-negative. With the standard formula max(min(blksize, 8MB), DEFAULT_BUFFER_SIZE) it is effectively unreachable through the public API.

Source

Thrown at Lib/_pyio.py:249

                      "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 "") +
                 (updating and "+" or ""),
                 closefd, opener=opener)
    result = raw
    try:
        line_buffering = False
        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

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. If you control the raw IO class, ensure its _blksize attribute is a sane positive int.
  2. Pass an explicit positive buffering value (e.g. 64*1024) to bypass default-size computation.
  3. If you patched _pyio/open constants, restore them or recompute the default so it is non-negative.

Example fix

// before
class OddRaw(io.RawIOBase):
    _blksize = -1        # corrupt block size defeats default resolution
open('f', 'rb', buffering=-1, ...)   # defensive ValueError path

// after
class OddRaw(io.RawIOBase):
    _blksize = io.DEFAULT_BUFFER_SIZE
# or sidestep defaults:
open('f', 'rb', buffering=65536)
Defensive patterns

Strategy: validation

Validate before calling

if buffering is not None and buffering <= 0:
    buffering = io.DEFAULT_BUFFER_SIZE   # never hand negative sizes around
open(path, buffering=buffering if buffering is not None else -1)

Prevention

When it happens

Trigger: Not reachable via normal open() calls: any negative buffering is replaced by a default >= DEFAULT_BUFFER_SIZE (8192). It could only fire if the underlying raw FileIO reported a corrupt/absurd _blksize such that the computed default stayed negative, or in patched/alternative IO stacks that reuse this logic with different constants.

Common situations: Developers grep this message after seeing it from a monkeypatched or reimplemented open (test doubles, custom raw IO classes in embedded interpreters, vendored _pyio with modified constants). Standard CPython users do not hit it.

Related errors


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