apache/beam · error · RuntimeError
Trying to append to a cleared ListBuffer.
Error message
Trying to append to a cleared ListBuffer.
What it means
ListBuffer.extend() refuses to append another Buffer's inputs once this buffer has been cleared via clear(). After clear(), _inputs is emptied and cleared=True marks the buffer dead; extending it would corrupt the bundle-buffer reuse protocol used by the fn_api_runner. A RuntimeError is raised to surface the lifecycle violation.
Solutions
- Call reset() on the cleared buffer before extending it again, or create a fresh ListBuffer.
- Restructure code so clear() is the last operation on a buffer (clear only when done).
- Track buffer lifecycle explicitly (e.g. set reference to None after clear) to avoid accidental reuse.
Example fix
# before buf.clear() buf.extend(other) # RuntimeError # after buf.clear() buf.reset() buf.extend(other)
Defensive patterns
Strategy: type-guard
Validate before calling
if buffer.cleared:
buffer.reset()
buffer.extend(other) Type guard
def is_writable(buf):
return not buf.cleared and not getattr(buf, '_grouped_output', None) Try / catch
try:
buffer.extend(other)
except RuntimeError:
buffer = ListBuffer(coder_impl)
buffer.extend(other) Prevention
- Never reuse a buffer after clear(); drop the reference instead.
- Call reset() immediately after clear() when reuse is intended.
- Keep a single owner responsible for buffer lifecycle transitions.
When it happens
Trigger: Calling buffer.extend(other) after buffer.clear() has been called (cleared is True), typically when reusing a cached Buffer object across bundle executions instead of calling reset() first.
Common situations: Runner-side code caching ListBuffer instances between bundles and forgetting reset(); custom runner extensions that clear a buffer then continue writing; race between a clearing thread and an appending thread.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Grouping table append after read.
- ListBuffer append after read.
- Trying to iterate through a cleared ListBuffer.
- Trying to partition a cleared ListBuffer.
- Trying to reset a non-cleared ListBuffer.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/48e874a9c78d5940.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/runners/portability/fn_api_runner/execution.py:134
pass
class ListBuffer:
"""Used to support parititioning of a list."""
def __init__(self, coder_impl: Optional[CoderImpl]) -> None:
self._coder_impl = coder_impl or CoderImpl()
self._inputs: list[bytes] = []
self._grouped_output: Optional[list[list[bytes]]] = None
self.cleared = False
def copy(self) -> 'ListBuffer':
new = ListBuffer(self._coder_impl)
new._inputs = [v for v in self._inputs]
return new
def extend(self, extra: 'Buffer') -> None:
if self.cleared:
raise RuntimeError('Trying to append to a cleared ListBuffer.')
if self._grouped_output:
raise RuntimeError('ListBuffer append after read.')
assert isinstance(extra, ListBuffer)
self._inputs.extend(extra._inputs)
def append(self, element: bytes) -> None:
if self.cleared:
raise RuntimeError('Trying to append to a cleared ListBuffer.')
if self._grouped_output:
raise RuntimeError('ListBuffer append after read.')
self._inputs.append(element)
def partition(self, n: int) -> list[list[bytes]]:
if self.cleared:
raise RuntimeError('Trying to partition a cleared ListBuffer.')
if len(self._inputs) >= n or len(self._inputs) == 0:
return [self._inputs[k::n] for k in range(n)]
else:View on GitHub (pinned to 12126d8942)