python/cpython · error · OSError
seek() returned an invalid position
Error message
seek() returned an invalid position
What it means
BufferedRaw.seek (Lib/_pyio.py:782) delegates to the underlying raw stream's seek(pos, whence) and validates the result: a seek must return the new absolute position, which can never be negative. If the raw object returns a negative number, the buffered layer raises a plain OSError because the raw stream is broken or misimplemented.
Source
Thrown at Lib/_pyio.py:782
class _BufferedIOMixin(BufferedIOBase):
"""A mixin implementation of BufferedIOBase with an underlying raw stream.
This passes most requests on to the underlying raw stream. It
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:View on GitHub (pinned to bc6749cc3b)
Solutions
- Fix the custom raw seek() to return the new absolute position (a non-negative int) on success.
- On failure, raise OSError from the raw seek() instead of returning a sentinel like -1.
- If the underlying object is not seekable, return 0-style identity or raise OSError(ESPIPE) from seekable() checks, and have callers honor seekable() before calling seek().
Example fix
# before
class MyRaw(io.RawIOBase):
def seek(self, pos, whence=0):
if whence != 0:
return -1 # -> OSError: seek() returned an invalid position
self._off = pos
return self._off
# after
class MyRaw(io.RawIOBase):
def seek(self, pos, whence=0):
if whence != 0:
raise OSError('unsupported whence')
self._off = pos
return self._off # always a non-negative absolute position Defensive patterns
Strategy: validation
Validate before calling
if not f.seekable():
raise OSError('stream is not seekable')
new_pos = f.seek(pos, whence) # raw layer validates the returned position Try / catch
try:
f.seek(0)
except OSError as e:
if 'invalid position' in str(e):
# underlying raw stream is broken; cannot recover transparently
raise
raise Prevention
- Custom raw seek() must return the new absolute position (non-negative int), never -1.
- Raise OSError on failure inside the raw layer instead of returning sentinels.
- Check seekable() before seeking streams you do not control.
When it happens
Trigger: A custom raw stream whose seek() returns -1 on failure (a C-convention errno style) instead of raising; seek() returning the whence-relative offset or an uninitialized variable; wrapping a device or socket-like object in a buffered reader without a real seek.
Common situations: Porting C library wrappers that use -1 sentinel returns; mocking raw.seek in tests to return -1; implementing file-like adapters over pipes or sockets where seek is meaningless but implemented anyway.
Related errors
- tell() returned an invalid position
- readinto returned {n} outside buffer size {len(b)}
- write() returned incorrect number of bytes
- seek() returned invalid position
- %s.%s() not supported
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/73280d5606dcead1.
Report an issue: GitHub.