RustPython/RustPython · error · TypeError

{pos!r} is not an integer

Error message

{pos!r} is not an integer

What it means

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.

Source

Thrown at Lib/_pyio.py:966

            n = view.nbytes  # Size of any bytes-like object
            if n == 0:
                return 0

            pos = self._pos
            if pos > len(self._buffer):
                # Pad buffer to pos with null bytes.
                self._buffer.resize(pos)
            self._buffer[pos:pos + n] = view
            self._pos += n
        return n

    def seek(self, pos, whence=0):
        if self.closed:
            raise ValueError("seek on closed file")
        try:
            pos_index = pos.__index__
        except AttributeError:
            raise TypeError(f"{pos!r} is not an integer")
        else:
            pos = pos_index()
        if whence == 0:
            if pos < 0:
                raise ValueError("negative seek position %r" % (pos,))
            self._pos = pos
        elif whence == 1:
            self._pos = max(0, self._pos + pos)
        elif whence == 2:
            self._pos = max(0, len(self._buffer) + pos)
        else:
            raise ValueError("unsupported whence value")
        return self._pos

    def tell(self):
        if self.closed:
            raise ValueError("tell on closed file")
        return self._pos

View on GitHub (pinned to aaeab4f754)

Solutions

  1. Convert before calling: buf.seek(int(pos)) or buf.seek(operator.index(pos))
  2. Use integer arithmetic (// and math.ceil wrapped in int) when computing offsets
  3. Coerce positions to int once at your API boundary

Example fix

// before
buf.seek(start / 2)  # float -> TypeError: 5.0 is not an integer

// after
buf.seek(start // 2)  # int
Defensive patterns

Strategy: type-guard

Validate before calling

import operator
pos = operator.index(pos)
buf.seek(pos, whence)

Type guard

def is_indexable(v) -> bool:
    return hasattr(v, "__index__")

Try / catch

try:
    buf.seek(pos, whence)
except TypeError as e:
    if "is not an integer" in str(e):
        buf.seek(int(pos), whence)
    else:
        raise

Prevention

When it happens

Trigger: buf.seek(2.0); buf.seek('10'); buf.seek(Decimal('3')); positions computed with true division (offset / 2) instead of floor division.

Common situations: Offsets derived from float math or percentages; values read from JSON/config that arrive as strings or floats; numpy scalars of float dtype.

Related errors


AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17). Data as JSON: /api/errors/0d4af85b611685c4. Report an issue: GitHub.