python/cpython · error · OSError

tell() returned an invalid position

Error message

tell() returned an invalid position

What it means

BufferedRaw.tell (Lib/_pyio.py:788) forwards to the raw stream's tell() and rejects negative results with OSError, since a stream position is by definition non-negative. Like its seek() sibling, this error indicates the underlying raw object violates the file-object protocol, not that the caller passed bad input.

Source

Thrown at Lib/_pyio.py:788

    does *not* provide implementations of read(), readinto() or
    write().
    """

    def __init__(self, raw):
        self._raw = raw

    ### Positioning ###

    def seek(self, pos, whence=0):
        new_position = self.raw.seek(pos, whence)
        if new_position < 0:
            raise OSError("seek() returned an invalid position")
        return new_position

    def tell(self):
        pos = self.raw.tell()
        if pos < 0:
            raise OSError("tell() returned an invalid position")
        return pos

    def truncate(self, pos=None):
        self._checkClosed()
        self._checkWritable()

        # Flush the stream.  We're mixing buffered I/O with lower-level I/O,
        # and a flush may be necessary to synch both views of the current
        # file state.
        self.flush()

        if pos is None:
            pos = self.tell()
        # XXX: Should seek() be used, instead of passing the position
        # XXX  directly to truncate?
        return self.raw.truncate(pos)

    ### Flush and close ###

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Fix the custom tell() to always return a non-negative absolute offset (track position internally if the source has no tell).
  2. Raise OSError in tell() when the underlying source genuinely cannot report position, and have callers check seekable()/handle the exception.
  3. For non-seekable sources, prefer not implementing tell/seek at all and set seekable() to False.

Example fix

# before
class MyRaw(io.RawIOBase):
    def tell(self):
        return -1  # before first read -> OSError

# after
class MyRaw(io.RawIOBase):
    def __init__(self):
        self._off = 0
    def tell(self):
        return self._off  # maintained by read/seek
Defensive patterns

Strategy: validation

Validate before calling

pos = f.tell() if f.seekable() else None  # honor capability before asking position
if pos is None:
    track_offset_manually = True

Try / catch

try:
    pos = f.tell()
except OSError as e:
    if 'invalid position' in str(e):
        pos = None  # raw layer broken or untracked; degrade explicitly
    else:
        raise

Prevention

When it happens

Trigger: A custom raw stream whose tell() returns -1 before any read/seek, or returns the result of a failed lseek; tell() returning a signed arithmetic result that underflowed; a mock raw object with an incorrect tell stub.

Common situations: Wrapping non-seekable or stateful transports (pipes, compressed chunk readers) in BufferedReader and calling tell(); C-extension streams leaking -1 sentinels; test doubles returning -1 by copy-paste from C examples.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/9452234ae410de40. Report an issue: GitHub.