python/cpython · error · ValueError
Limit cannot be <= 0
Error message
Limit cannot be <= 0
What it means
ValueError raised by StreamReader.__init__ when the limit argument is zero or negative. The limit is both the readline/readuntil separator length bound and half the flow-control buffer size, so a non-positive value is meaningless and rejected immediately at construction.
Source
Thrown at Lib/asyncio/streams.py:420
def __del__(self, warnings=warnings):
if not self._transport.is_closing():
if self._loop.is_closed():
warnings.warn("loop is closed", ResourceWarning)
else:
self.close()
warnings.warn(f"unclosed {self!r}", ResourceWarning)
class StreamReader:
_source_traceback = None
def __init__(self, limit=_DEFAULT_LIMIT, loop=None):
# The line length limit is a security feature;
# it also doubles as half the buffer limit.
if limit <= 0:
raise ValueError('Limit cannot be <= 0')
self._limit = limit
if loop is None:
self._loop = events.get_event_loop()
else:
self._loop = loop
self._buffer = bytearray()
self._eof = False # Whether we're done.
self._waiter = None # A future used by _wait_for_data()
self._exception = None
self._transport = None
self._paused = False
if self._loop.get_debug():
self._source_traceback = format_helpers.extract_stack(
sys._getframe(1))
def __repr__(self):
info = ['StreamReader']View on GitHub (pinned to bc6749cc3b)
Solutions
- Pass a positive limit (default is 64 KiB, _DEFAULT_LIMIT); choose it deliberately given readline/readuntil semantics
- Validate/derive config values at startup: limit = max(1, configured) only if a sane default is intended, otherwise fail fast with a clear config error
- If you meant 'no line limit', pick a large explicit value rather than 0 — the parameter is not an on/off switch
Example fix
// before
reader, writer = await asyncio.open_connection(host, port, limit=cfg.max_line_bytes) # cfg value 0
// after
if cfg.max_line_bytes <= 0:
raise ValueError(f'max_line_bytes must be > 0, got {cfg.max_line_bytes}')
reader, writer = await asyncio.open_connection(host, port, limit=cfg.max_line_bytes) Defensive patterns
Strategy: validation
Validate before calling
def checked_limit(value: int) -> int:
if not isinstance(value, int) or value <= 0:
raise ValueError(f'stream limit must be a positive int, got {value!r}')
return value Type guard
null
Try / catch
null
Prevention
- Validate stream/buffer settings once at startup with clear config-error messages
- Treat a 0 in config as 'unset' and substitute the documented default explicitly, never pass it through
- Remember limit bounds readline/readuntil separator length and half the buffer — size it from protocol requirements
When it happens
Trigger: StreamReader(limit=0), StreamReader(limit=-1), or asyncio.open_connection/start_server(..., limit=n) with n <= 0; typically the value comes from a config value, CLI flag, or arithmetic that evaluated to zero.
Common situations: A 'max line length' setting defaulting to 0 meaning 'unset'; computing limit as a difference or percentage that collapses to 0; passing a buffer-size knob meant for something else into the streams limit parameter.
Related errors
- Separator should contain at least one element
- Separator should be at least one-byte string
- readexactly size can not be less than zero
- Unimplemented ioctl request
- profiling_trace: Placeholder pattern not found in {js_path.n
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/620e4c99bd881b6d.
Report an issue: GitHub.