python/cpython · error · ValueError

readexactly size can not be less than zero

Error message

readexactly size can not be less than zero

What it means

ValueError raised by StreamReader.readexactly() when n is negative. The function's contract is to return exactly n bytes (or raise IncompleteReadError), which is meaningless for negative n, so it fails fast before checking the buffer.

Source

Thrown at Lib/asyncio/streams.py:752

        return data

    async def readexactly(self, n):
        """Read exactly `n` bytes.

        Raise an IncompleteReadError if EOF is reached before `n` bytes can be
        read. The IncompleteReadError.partial attribute of the exception will
        contain the partial read bytes.

        if n is zero, return empty bytes object.

        Returned value is not limited with limit, configured at stream
        creation.

        If stream was paused, this function will automatically resume it if
        needed.
        """
        if n < 0:
            raise ValueError('readexactly size can not be less than zero')

        if self._exception is not None:
            raise self._exception

        if n == 0:
            return b''

        while len(self._buffer) < n:
            if self._eof:
                incomplete = self._buffer.take_bytes()
                raise exceptions.IncompleteReadError(incomplete, n)

            await self._wait_for_data('readexactly')

        data = self._buffer.take_bytes(n)
        self._maybe_resume_transport()
        return data

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Validate n >= 0 before the call and fail with a protocol-framing error if the peer sent a bogus length
  2. Check your size arithmetic: clamp or assert on intermediate values in the framing loop early (fail fast at parse time)
  3. Use reader.read(n) for variable-length reads and readexactly only with a validated non-negative count

Example fix

// before
payload = await reader.readexactly(declared_len - header_size)  # can go negative

// after
n = declared_len - header_size
if n < 0:
    raise ProtocolError(f'bad length: {declared_len}')
payload = await reader.readexactly(n)
Defensive patterns

Strategy: validation

Validate before calling

def checked_read_size(n: int) -> int:
    if not isinstance(n, int) or n < 0:
        raise ValueError(f'readexactly size must be >= 0, got {n!r}')
    return n

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: await reader.readexactly(n) where n is a computed length that went negative: size arithmetic like remaining - chunk with unsigned underflow in concept, a parsed header length field with a negative value, or -1 used as a sentinel reaching this call.

Common situations: Protocol parsers reading a length prefix that was validated nowhere; slicing/subtraction mistakes in framing loops; passing a 'read all' sentinel (-1) from a different API into readexactly.

Related errors


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