RustPython/RustPython · error · ValueError
negative truncate position %r
Error message
negative truncate position %r
What it means
BytesIO.truncate (Lib/_pyio.py:999) raises ValueError('negative truncate position %r' % (pos,)) when an explicitly passed pos is negative after integer coercion. truncate(None) uses the current position and never fails this check; only an explicit negative size does, because an in-memory buffer cannot have a negative length. OS files would fail with EINVAL at the ftruncate level; BytesIO enforces the same rule in Python.
Source
Thrown at Lib/_pyio.py:999
def tell(self):
if self.closed:
raise ValueError("tell on closed file")
return self._pos
def truncate(self, pos=None):
if self.closed:
raise ValueError("truncate on closed file")
if pos is None:
pos = self._pos
else:
try:
pos_index = pos.__index__
except AttributeError:
raise TypeError(f"{pos!r} is not an integer")
else:
pos = pos_index()
if pos < 0:
raise ValueError("negative truncate position %r" % (pos,))
del self._buffer[pos:]
return pos
def readable(self):
if self.closed:
raise ValueError("I/O operation on closed file.")
return True
def writable(self):
if self.closed:
raise ValueError("I/O operation on closed file.")
return True
def seekable(self):
if self.closed:
raise ValueError("I/O operation on closed file.")
return True
View on GitHub (pinned to aaeab4f754)
Solutions
- Clamp the argument: buf.truncate(max(0, pos))
- Omit the argument (or pass None) to truncate at the current position
- Recompute sizes defensively: new_size = max(0, len(buf) - extra)
Example fix
// before buf.truncate(len(buf.getvalue()) - overhead) # negative when overhead > size // after buf.truncate(max(0, len(buf.getvalue()) - overhead))
Defensive patterns
Strategy: validation
Validate before calling
buf.truncate(max(0, pos)) if pos is not None else buf.truncate()
Try / catch
try:
buf.truncate(pos)
except ValueError as e:
if "negative truncate position" in str(e):
buf.truncate(0)
else:
raise Prevention
- Clamp computed sizes with max(0, ...)
- Pass None (or nothing) to truncate at the current position
- Treat negative sizes from user input as validation errors, not seek targets
When it happens
Trigger: buf.truncate(-1); buf.truncate(len(buf) - extra) where extra > len(buf); negative sizes computed by subtraction without clamping.
Common situations: Size-cap code that subtracts an overhead/allowance from the current length; ported file-ftruncate logic; input-derived sizes that can go negative on malformed data.
Related errors
- negative seek position %r
- truncate on closed file
- __getstate__ on closed file
- getvalue on closed file
- getbuffer on closed file
AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17).
Data as JSON: /api/errors/db832648be91a0cb.
Report an issue: GitHub.