{"record":{"id":"0d4af85b611685c4","repo":"RustPython/RustPython","slug":"pos-r-is-not-an-integer","errorCode":null,"errorMessage":"{pos!r} is not an integer","messagePattern":"(.+?) is not an integer","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":966,"sourceCode":"            n = view.nbytes  # Size of any bytes-like object\n            if n == 0:\n                return 0\n\n            pos = self._pos\n            if pos > len(self._buffer):\n                # Pad buffer to pos with null bytes.\n                self._buffer.resize(pos)\n            self._buffer[pos:pos + n] = view\n            self._pos += n\n        return n\n\n    def seek(self, pos, whence=0):\n        if self.closed:\n            raise ValueError(\"seek on closed file\")\n        try:\n            pos_index = pos.__index__\n        except AttributeError:\n            raise TypeError(f\"{pos!r} is not an integer\")\n        else:\n            pos = pos_index()\n        if whence == 0:\n            if pos < 0:\n                raise ValueError(\"negative seek position %r\" % (pos,))\n            self._pos = pos\n        elif whence == 1:\n            self._pos = max(0, self._pos + pos)\n        elif whence == 2:\n            self._pos = max(0, len(self._buffer) + pos)\n        else:\n            raise ValueError(\"unsupported whence value\")\n        return self._pos\n\n    def tell(self):\n        if self.closed:\n            raise ValueError(\"tell on closed file\")\n        return self._pos","sourceCodeStart":948,"sourceCodeEnd":984,"githubUrl":"https://github.com/RustPython/RustPython/blob/aaeab4f754b4f40efc0c8ab39cf7c4a3c35a8cfd/Lib/_pyio.py#L948-L984","documentation":"BytesIO.seek (Lib/_pyio.py:966) coerces the pos argument through __index__; objects without it (str, float, Decimal) raise TypeError formatted as \"{pos!r} is not an integer\". Positions must be exact integers — floats are never implicitly truncated, mirroring CPython's PyNumber_Index behavior. The closed-file check runs first, so this only fires on an open buffer.","triggerScenarios":"buf.seek(2.0); buf.seek('10'); buf.seek(Decimal('3')); positions computed with true division (offset / 2) instead of floor division.","commonSituations":"Offsets derived from float math or percentages; values read from JSON/config that arrive as strings or floats; numpy scalars of float dtype.","solutions":["Convert before calling: buf.seek(int(pos)) or buf.seek(operator.index(pos))","Use integer arithmetic (// and math.ceil wrapped in int) when computing offsets","Coerce positions to int once at your API boundary"],"exampleFix":"// before\nbuf.seek(start / 2)  # float -> TypeError: 5.0 is not an integer\n\n// after\nbuf.seek(start // 2)  # int","handlingStrategy":"type-guard","validationCode":"import operator\npos = operator.index(pos)\nbuf.seek(pos, whence)","typeGuard":"def is_indexable(v) -> bool:\n    return hasattr(v, \"__index__\")","tryCatchPattern":"try:\n    buf.seek(pos, whence)\nexcept TypeError as e:\n    if \"is not an integer\" in str(e):\n        buf.seek(int(pos), whence)\n    else:\n        raise","preventionTips":["Use integer math (//) when computing offsets","Coerce positions with operator.index before calling seek","Validate external offset inputs at the boundary"],"tags":["python","io","bytesio","seek","typeerror","argument-type"],"backgroundTag":"non-integer-argument","analyzedSha":"aaeab4f754b4f40efc0c8ab39cf7c4a3c35a8cfd","analyzedAt":"2026-08-17T00:37:52.100Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}