python/cpython · error · ValueError
negative seek position %r
Error message
negative seek position %r
What it means
BytesIO.seek (Lib/_pyio.py:986) raises ValueError('negative seek position') when whence is 0 (SEEK_SET, the default) and pos is negative. An absolute position cannot be below zero, so instead of clamping or wrapping around, BytesIO rejects it outright. Note the whence==1 and whence==2 branches clamp with max(0, ...) — only absolute seeks are strict.
Source
Thrown at Lib/_pyio.py:986
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:
with self._lock:
self._pos = max(0, self._pos + pos)
elif whence == 2:
with self._lock:
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
def peek(self, size=0):
if self.closed:View on GitHub (pinned to bc6749cc3b)
Solutions
- For positions relative to the end, pass the whence explicitly: `buf.seek(-4, io.SEEK_END)`.
- For relative moves use `buf.seek(-4, io.SEEK_CUR)`.
- Validate computed absolute offsets: `pos = max(0, computed)` only if clamping is intended, otherwise treat negative values as a parsing error.
Example fix
# before buf.seek(-4) # absolute negative -> ValueError # after buf.seek(-4, io.SEEK_END) # 4 bytes before end, as intended
Defensive patterns
Strategy: validation
Validate before calling
import io
def seek_absolute(buf: io.BytesIO, pos: int):
if pos < 0:
raise ValueError(f'absolute seek position must be >= 0, got {pos}')
buf.seek(pos, io.SEEK_SET) Try / catch
try:
buf.seek(pos)
except ValueError as e:
if 'negative seek position' in str(e):
buf.seek(0) # or raise a parse error: negative absolute offset is a logic bug
else:
raise Prevention
- Remember default whence is SEEK_SET (absolute); use io.SEEK_END/io.SEEK_CUR for negative offsets.
- Validate computed offsets (`start - consumed`) and treat negatives as upstream parse errors.
- Use the io.SEEK_* constants so intent is explicit in code review.
When it happens
Trigger: buf.seek(-4) or buf.seek(-4, io.SEEK_SET); passing a negative offset computed from a header that turns out larger than expected; reusing socket-style negative offsets (meaning 'relative to end') with the default whence.
Common situations: Mixing up whence conventions: expecting seek(-n) to be relative (it is absolute by default); unsigned-length underflow from struct unpacking; backtracking computed as start - consumed where consumed > start.
Related errors
- unsupported whence value
- seek on closed file
- __getstate__ on closed file
- getvalue on closed file
- getbuffer on closed file
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/659a0feb5945bccc.
Report an issue: GitHub.