BufferError

A memoryview points straight at an object's memory, so while one exists the object may change its bytes but not its length.

InheritsBaseException›Exception›BufferError
Runtime exceptionPython 3 (all)Live demo
BufferError(*args)
Raised by
append/extend/pop/clear/resizing slice on a bytearray with a live memoryview; BytesIO.write after getbuffer()
Message
Existing exports of data: object cannot be re-sized
Quick fix
view.release() or with memoryview(buf) as view:
Watch out
slices of a memoryview are exports too

Demo

Live evaluation
Replace the first byte while a memoryview is alive. Same length is fine; any other length is a resize.
Try:
Inputs
newstrencoded to UTF-8
Code
buf = bytearray(b'abc')
view = memoryview(buf)
buf[0:1] = 'X'.encode()
bytes(buf)
Result
b'Xbc'

'X' works because it is exactly one byte and the length stays 3. 'é' looks like one character but .encode() makes it two bytes, so it is a resize and fails like 'XYZ' and ''. In Handle, the view is already released when the assignment runs, and every input succeeds.

Constructor

NameTypeRequiredDescription
*argsobjectnoThe message. Built-in types pass one string describing what could not be done.

Attributes

AttributeTypeMeaning
argstupleThe message tuple, e.g. ('Existing exports of data: object cannot be re-sized',).

Common patterns

Scope the view with with
memoryview is a context manager; leaving the block releases the export deterministically.
with memoryview(buf) as view:
    header = bytes(view[:4])
buf.extend(more)
Release explicitly
When the view must outlive a block, release it before the next resize.
view = memoryview(buf)
process(view)
view.release()
buf.clear()
BytesIO.getbuffer() the same way
getbuffer() returns a memoryview over the BytesIO; writes and close() fail while it lives.
stream = io.BytesIO()
with stream.getbuffer() as view:
    checksum = zlib.crc32(view)
stream.write(b'more')

Examples

1. append() with a live view
buf = bytearray(b'abc') view = memoryview(buf) buf.append(100)
Returns
BufferError: Existing exports of data: object cannot be re-sized
2. In-place change is allowed
buf = bytearray(b'abc') view = memoryview(buf) view[0] = 88 buf
Returns
bytearray(b'Xbc')
3. A view slice is an export too
buf = bytearray(b'abc') tail = memoryview(buf)[1:] buf.clear()
Returns
BufferError: Existing exports of data: object cannot be re-sized
4. release() lifts the lock
buf = bytearray(b'abc') view = memoryview(buf) view.release() buf.append(100) buf
Returns
bytearray(b'abcd')
5. BytesIO after getbuffer()
import io stream = io.BytesIO(b'abc') view = stream.getbuffer() stream.write(b'x')
Returns
BufferError: Existing exports of data: object cannot be re-sized
6. array.array has its own message
from array import array a = array('i', [1]) view = memoryview(a) a.append(2)
Returns
BufferError: cannot resize an array that is exporting buffers
7. A released view cannot be used
buf = bytearray(b'abc') view = memoryview(buf) view.release() view[0]
Returns
ValueError: operation forbidden on released memoryview object

Pitfalls

1. A forgotten view blocks the buffer
Keeping a memoryview in a variable "for later" keeps the bytearray locked at its size. Scope it.
View left alive
buf = bytearray(b'hdr')
view = memoryview(buf)
header = bytes(view[:3])
buf.extend(b'body')
BufferError: Existing exports of data: object cannot be re-sized
with block
buf = bytearray(b'hdr')
with memoryview(buf) as view:
    header = bytes(view[:3])
buf.extend(b'body')
buf
bytearray(b'hdrbody')
2. close() on BytesIO with getbuffer() alive
Closing frees the buffer, which counts as a resize — it fails the same way as write().
close() first
import io
stream = io.BytesIO(b'data')
view = stream.getbuffer()
stream.close()
BufferError: Existing exports of data: object cannot be re-sized
Release, then close
import io
stream = io.BytesIO(b'data')
view = stream.getbuffer()
size = len(view)
view.release()
stream.close()
size
4

When to use

Use it
  • Raising it from your own C extension or buffer-exporting type when a buffer request cannot be met
  • Recognising "a memoryview is still alive somewhere" in a traceback
Reach for something else
  • Holding memoryviews longer than needed
  • Assuming del view always frees the export — another name, a slice, or a traceback frame may still hold it; release() is explicit

Notes

CPython impl
Objects/bytearrayobject.c — resizing checks ob_exports and refuses when it is non-zero
Not affected
bytes objects are immutable, so they never need to refuse a resize
Exporters
bytearray, array.array, io.BytesIO (getbuffer), mmap, NumPy arrays

FAQ

Some memoryview (or a slice of one, or a BytesIO.getbuffer() result) still refers to the object you are resizing. Call view.release() before the append/extend/write/close, or create the view in a with memoryview(obj) as view: block so it is released automatically. In-place changes that keep the length — view[0] = 1 or buf[0:1] = b"X" — are allowed while the view exists.