python/cpython · error · OSError
seek() returned invalid position
Error message
seek() returned invalid position
What it means
Raised by BufferedRandom.seek() when the underlying raw stream's seek() returns a negative position. The code deliberately performs the raw seek first and only then resets the read buffer, so a negative return indicates the raw object violated the IO protocol (positions must be non-negative); the buffer state is not the cause but the trigger is the raw layer.
Source
Thrown at Lib/_pyio.py:1451
raw._checkSeekable()
BufferedReader.__init__(self, raw, buffer_size)
BufferedWriter.__init__(self, raw, buffer_size)
def seek(self, pos, whence=0):
if whence not in valid_seek_flags:
raise ValueError("invalid whence value")
self.flush()
if self._read_buf:
# Undo read ahead.
with self._read_lock:
self.raw.seek(self._read_pos - len(self._read_buf), 1)
# First do the raw seek, then empty the read buffer, so that
# if the raw seek fails, we don't lose buffered data forever.
pos = self.raw.seek(pos, whence)
with self._read_lock:
self._reset_read_buf()
if pos < 0:
raise OSError("seek() returned invalid position")
return pos
def tell(self):
if self._write_buf:
return BufferedWriter.tell(self)
else:
return BufferedReader.tell(self)
def truncate(self, pos=None):
if pos is None:
pos = self.tell()
# Use seek to flush the read buffer.
return BufferedWriter.truncate(self, pos)
def read(self, size=None):
if size is None:
size = -1
self.flush()View on GitHub (pinned to bc6749cc3b)
Solutions
- Fix the underlying raw object: seek() must return the new non-negative offset or raise OSError, never a negative number
- In tests, make mock raw streams return a valid int (e.g. the requested offset)
- If you cannot fix the raw class, wrap it and clamp/convert negative returns into an OSError
Example fix
# before
class MyRaw(io.RawIOBase):
def seek(self, pos, whence=0):
return -1 # signals failure -> OSError: seek() returned invalid position
# after
class MyRaw(io.RawIOBase):
def seek(self, pos, whence=0):
new = self._do_seek(pos, whence)
if new < 0:
raise OSError('seek failed')
return new Defensive patterns
Strategy: try-catch
Try / catch
try:
new_pos = f.seek(pos, whence)
except OSError as e:
if 'invalid position' in str(e):
# raw layer misbehaved; reopen or resync the stream
pos_now = f.raw.seek(0, os.SEEK_CUR)
raise RuntimeError(f'raw seek broken, current={pos_now}') from e
raise Prevention
- Custom raw seek() must return a non-negative int or raise OSError — never -1
- Property-test custom file objects against io.BufferedRandom to catch protocol violations
- In mocks, return the requested offset from seek stubs
When it happens
Trigger: A custom RawIOBase-like object whose seek() returns -1 or another negative value on failure instead of raising OSError; mocked raw streams in tests stubbed to return -1; a raw wrapper around an exotic device where a negative result leaks through from the OS layer without being converted to an exception.
Common situations: Writing custom file-like objects (protocol implementations for SFTP/blob storage) that copy C conventions of returning -1 on error; test doubles with incorrect seek return values; partially-implemented adapters between file APIs.
Related errors
- seek() returned an invalid position
- "raw" argument must be readable.
- invalid whence value
- "raw" argument must be writable.
- write() returned incorrect number of bytes
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/54a3ec675877d6da.
Report an issue: GitHub.