openai/openai-python · error · RuntimeError
Could not read bytes from {data}; Received {type(binary)}
Error message
Could not read bytes from {data}; Received {type(binary)} What it means
When a request body field is typed as a file/upload, the SDK calls .read() on the object and base64-encodes the result for JSON transport. This RuntimeError means the object's read() returned something that is neither bytes nor a str (e.g. a memoryview, bytearray consumed incorrectly, or a custom file-like object returning a generator). The sync transform could not produce bytes to encode, so serialization of the request body fails before sending.
Source
Thrown at src/openai/_utils/_transform.py:256
if format_ == "iso8601":
return data.isoformat()
if format_ == "custom" and format_template is not None:
return data.strftime(format_template)
if format_ == "base64" and is_base64_file_input(data):
binary: str | bytes | None = None
if isinstance(data, pathlib.Path):
binary = data.read_bytes()
elif isinstance(data, io.IOBase):
binary = data.read()
if isinstance(binary, str): # type: ignore[unreachable]
binary = binary.encode()
if not isinstance(binary, bytes):
raise RuntimeError(f"Could not read bytes from {data}; Received {type(binary)}")
return base64.b64encode(binary).decode("ascii")
return data
def _transform_typeddict(
data: Mapping[str, object],
expected_type: type,
) -> Mapping[str, object]:
result: dict[str, object] = {}
annotations = get_type_hints(expected_type, include_extras=True)
for key, value in data.items():
if not is_given(value):
# we don't need to include omitted values here as they'll
# be stripped out before the request is sent anyway
continue
View on GitHub (pinned to 9917c6e28e)
Solutions
- Ensure the object passed for the file field has read() returning bytes (encode str results)
- Wrap custom streams: read = lambda *a: raw.read() or return bytes(memoryview_chunk) from read()
- Pass raw bytes or a real file object opened in binary mode ('rb')
- Add a unit test asserting your upload object's read() returns bytes
Example fix
# before
class WeirdFile:
def read(self): return memoryview(b"data")
client.models.create(file=WeirdFile())
# after
class BytesFile:
def read(self, *a): return b"data"
client.models.create(file=BytesFile()) Defensive patterns
Strategy: type-guard
Validate before calling
data = f.read() if hasattr(f, "read") else f assert isinstance(data, (bytes, bytearray)), type(data)
Type guard
def is_bytes_readable(obj: object) -> bool:
return isinstance(obj, (bytes, bytearray)) or (hasattr(obj, "read") and isinstance(getattr(obj, "read")(), (bytes, type(None)))) Try / catch
try:
client.models.create(file=f)
except RuntimeError as e:
raise ValueError("file must read() bytes") from e Prevention
- Open files in binary mode
- Keep custom read() returning bytes
- Unit test adapters' read() return type
When it happens
Trigger: Passing a custom file-like object whose read() returns a non-bytes value; passing a SpooledTemporaryFile wrapper or object wrapping bytes in memoryview; constructing models locally with an improper upload object and then serializing them.
Common situations: Custom IO abstractions (e.g. adapters around cloud storage streams) not returning bytes; wrapping files in classes that return the underlying buffer object; upgrading SDK versions where upload handling moved to the transform layer.
Related errors
- mode must be either 'json' or 'python'
- round_trip is only supported in Pydantic v2
- warnings is only supported in Pydantic v2
- context is only supported in Pydantic v2
- serialize_as_any is only supported in Pydantic v2
AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28).
Data as JSON: /api/errors/aed2a055773cf669.
Report an issue: GitHub.