python/cpython · error · TypeError
{size!r} is not an integer
Error message
{size!r} is not an integer What it means
Raised by IOBase.readline (Lib/_pyio.py:542) when the size argument does not implement __index__ (i.e. cannot be interpreted as an integer). The pure-Python io layer is strict: it converts size via size.__index__ and raises TypeError if that attribute is missing. This rejects floats, strings, or arbitrary objects passed as readline's size limit.
Source
Thrown at Lib/_pyio.py:542
if hasattr(self, "peek"):
def nreadahead():
readahead = self.peek(1)
if not readahead:
return 1
n = (readahead.find(b"\n") + 1) or len(readahead)
if size >= 0:
n = min(n, size)
return n
else:
def nreadahead():
return 1
if size is None:
size = -1
else:
try:
size_index = size.__index__
except AttributeError:
raise TypeError(f"{size!r} is not an integer")
else:
size = size_index()
res = bytearray()
while size < 0 or len(res) < size:
b = self.read(nreadahead())
if not b:
break
res += b
if res.endswith(b"\n"):
break
return res.take_bytes()
def __iter__(self):
self._checkClosed()
return self
def __next__(self):
line = self.readline()View on GitHub (pinned to bc6749cc3b)
Solutions
- Convert the value before the call: `f.readline(int(size))`.
- Use operator.index(size) if you want non-int integer-like types (numpy ints, enum IntEnum) to pass through unchanged.
- Validate at the API boundary that size is an int (isinstance check) and reject or coerce early.
Example fix
# before line = f.readline(max_len / 2) # float -> TypeError # after line = f.readline(max_len // 2) # int
Defensive patterns
Strategy: validation
Validate before calling
from operator import index size = index(user_size) # raises TypeError early with clear context line = f.readline(size)
Type guard
def is_indexable(v) -> bool:
return hasattr(v, '__index__') Try / catch
try:
line = f.readline(size)
except TypeError:
line = f.readline(int(size)) # coerce and retry Prevention
- Use `//` (floor division) whenever computing byte lengths.
- Convert numeric inputs to int at the API boundary (int() or operator.index()).
- Remember float sizes are always rejected — unlike Python slicing, io is strict here.
When it happens
Trigger: f.readline(1024.0) or f.readline('16'); passing a size computed by len()/division that yielded a float; forwarding an unvalidated user-supplied size parameter to readline.
Common situations: Computing a size with true division (`total / 2` instead of `total // 2`); API wrappers that accept a size hint from JSON or query strings and pass it through unconverted; numpy integer scalars (these do work via __index__, but numpy floats do not).
Related errors
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/872ae88fdbd663a9.
Report an issue: GitHub.