{"record":{"id":"872ae88fdbd663a9","repo":"python/cpython","slug":"size-r-is-not-an-integer","errorCode":null,"errorMessage":"{size!r} is not an integer","messagePattern":"(.+?) is not an integer","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":542,"sourceCode":"        if hasattr(self, \"peek\"):\n            def nreadahead():\n                readahead = self.peek(1)\n                if not readahead:\n                    return 1\n                n = (readahead.find(b\"\\n\") + 1) or len(readahead)\n                if size >= 0:\n                    n = min(n, size)\n                return n\n        else:\n            def nreadahead():\n                return 1\n        if size is None:\n            size = -1\n        else:\n            try:\n                size_index = size.__index__\n            except AttributeError:\n                raise TypeError(f\"{size!r} is not an integer\")\n            else:\n                size = size_index()\n        res = bytearray()\n        while size < 0 or len(res) < size:\n            b = self.read(nreadahead())\n            if not b:\n                break\n            res += b\n            if res.endswith(b\"\\n\"):\n                break\n        return res.take_bytes()\n\n    def __iter__(self):\n        self._checkClosed()\n        return self\n\n    def __next__(self):\n        line = self.readline()","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L524-L560","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"# before\nline = f.readline(max_len / 2)  # float -> TypeError\n\n# after\nline = f.readline(max_len // 2)  # int","handlingStrategy":"validation","validationCode":"from operator import index\nsize = index(user_size)  # raises TypeError early with clear context\nline = f.readline(size)","typeGuard":"def is_indexable(v) -> bool:\n    return hasattr(v, '__index__')","tryCatchPattern":"try:\n    line = f.readline(size)\nexcept TypeError:\n    line = f.readline(int(size))  # coerce and retry","preventionTips":["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."],"tags":["io","typeerror","readline","argument-validation"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}