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
- Fix the custom tell() to always return a non-negative absolute offset (track position internally if the source has no tell).
- Raise OSError in tell() when the underlying source genuinely cannot report position, and have callers check seekable()/handle the exception.
- 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
- Custom tell() must return a non-negative absolute offset; maintain your own counter if the source lacks one.
- Mark non-seekable sources with seekable() -> False and stop calling tell() on them.
- Never copy C-style -1 sentinel returns into Python file-like adapters.
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
- seek() returned an invalid position
- readinto returned {n} outside buffer size {len(b)}
- write() returned incorrect number of bytes
- %s.%s() not supported
- tell on closed file
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/9452234ae410de40.
Report an issue: GitHub.