apache/beam · error · ValueError
Output stream must be writable
Error message
Output stream must be writable
What it means
Raised by `JsonRowWriter.__init__` when the provided file_handle is not writable (file_handle.writable() is False). The writer needs an output stream it can write JSON rows to, so it fails immediately at construction rather than later on write. This guards against read-only handles or write-mode mistakes.
Solutions
- Open the file/buffer in write mode: open(path, 'wb') or io.BytesIO() (which is writable by default).
- Verify the handle with `assert file_handle.writable()` before constructing JsonRowWriter.
- If wrapping a stream, implement/forward writable() to return True and support write().
- Check that the handle wasn't closed earlier in the code path (closed streams return writable() == False).
Example fix
// before
f = open('rows.json', 'rb')
w = JsonRowWriter(f)
// after
f = open('rows.json', 'wb')
w = JsonRowWriter(f) Defensive patterns
Strategy: type-guard
Validate before calling
def assert_writable(handle):
if not handle.writable():
raise ValueError('JsonRowWriter requires a writable stream')
return handle Type guard
def is_writable_stream(h):
import io
return isinstance(h, io.IOBase) and h.writable() and not h.closed Try / catch
try:
writer = JsonRowWriter(handle)
except ValueError as e:
if str(e) == 'Output stream must be writable':
handle = open(path, 'wb')
writer = JsonRowWriter(handle)
else:
raise Prevention
- Always open writer destinations with 'wb' mode.
- Check handle.writable() and not handle.closed before constructing writers.
- Use io.BytesIO() (writable) for in-memory test sinks.
When it happens
Trigger: Constructing JsonRowWriter with a handle opened in read mode ('rb'/'r'), an io.BytesIO opened read-only, a closed stream, or a wrapper object whose writable() returns False.
Common situations: Copy-paste switching a reader to a writer without flipping the file mode; programmatically created buffers for testing opened without write flags; passing sys.stdin-like streams; passing an already-closed handle.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- AvroRowWriter is not readable
- JsonRowWriter is not readable
- Please specify a BigQuery table to read from.
- A BigQuery table or a query must be specified
- A schema is required to write non-schema'd data.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/dc142c17f6c84dc8.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/io/gcp/bigquery_tools.py:1471
return json.loads(encoded_table_row.decode('utf-8'))
def to_type_hint(self):
return Any
class JsonRowWriter(io.IOBase):
"""
A writer which provides an IOBase-like interface for writing table rows
(represented as dicts) as newline-delimited JSON strings.
"""
def __init__(self, file_handle):
"""Initialize an JsonRowWriter.
Args:
file_handle (io.IOBase): Output stream to write to.
"""
if not file_handle.writable():
raise ValueError("Output stream must be writable")
self._file_handle = file_handle
self._coder = RowAsDictJsonCoder()
def close(self):
self._file_handle.close()
@property
def closed(self):
return self._file_handle.closed
def flush(self):
self._file_handle.flush()
def read(self, size=-1):
raise io.UnsupportedOperation("JsonRowWriter is not readable")
def tell(self):View on GitHub (pinned to 12126d8942)