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

  1. Open the file/buffer in write mode: open(path, 'wb') or io.BytesIO() (which is writable by default).
  2. Verify the handle with `assert file_handle.writable()` before constructing JsonRowWriter.
  3. If wrapping a stream, implement/forward writable() to return True and support write().
  4. 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

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


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)