crewAIInc/crewAI · error · ValueError
Expected a binary file-like object with read() and seek()
Error message
Expected a binary file-like object with read() and seek()
What it means
Pydantic validator error from the BinaryIO schema: a value passed where a binary file-like object is expected lacks a 'read' or 'seek' attribute. Unlike the async validator, this one IS duck-typed — any object with read() and seek() passes. So hitting it means the value has neither or only one of the two methods, e.g. a text-mode file (which has both, so more commonly: an httpx/starlette response stream with no seek), a generator, or raw bytes.
Source
Thrown at lib/crewai-files/src/crewai_files/core/sources.py:200
class _BinaryIOValidator:
"""Pydantic validator for BinaryIO types."""
@classmethod
def __get_pydantic_core_schema__(
cls, _source_type: Any, _handler: GetCoreSchemaHandler
) -> CoreSchema:
return core_schema.no_info_plain_validator_function(
cls._validate,
serialization=core_schema.plain_serializer_function_ser_schema(
lambda x: None, info_arg=False
),
)
@staticmethod
def _validate(value: Any) -> BinaryIO:
if hasattr(value, "read") and hasattr(value, "seek"):
return cast(BinaryIO, value)
raise ValueError("Expected a binary file-like object with read() and seek()")
ValidatedBinaryIO = Annotated[BinaryIO, _BinaryIOValidator()]
class FilePath(BaseModel):
"""File loaded from a filesystem path."""
path: Path = Field(description="Path to the file on the filesystem.")
max_size_bytes: int = Field(
default=DEFAULT_MAX_FILE_SIZE_BYTES,
exclude=True,
description="Maximum file size in bytes.",
)
_content: bytes | None = PrivateAttr(default=None)
_content_type: str = PrivateAttr()
@model_validator(mode="after")View on GitHub (pinned to 754d7323be)
Solutions
- Buffer the data first: data = await response.read() then use FileBytes(data=data), or wrap in io.BytesIO which has both read() and seek().
- If wrapping a custom class, add seek() (and tell/read) or read the full payload eagerly.
- For files, open in binary mode: open(path, 'rb').
Example fix
# before resp = await client.get(url) fs = FileStream(stream=resp) # httpx response: no seek() # after resp = await client.get(url) fs = FileBytes(data=resp.content) # or FileStream(stream=io.BytesIO(resp.content))
Defensive patterns
Strategy: type-guard
Validate before calling
def is_binary_filelike(v) -> bool:
return hasattr(v, "read") and hasattr(v, "seek") Type guard
import io
def as_binary(v) -> io.BytesIO:
if isinstance(v, (bytes, bytearray)):
return io.BytesIO(v)
if hasattr(v, "read") and hasattr(v, "seek"):
return v
raise TypeError(f"{type(v).__name__} is not a binary file-like object") Try / catch
try:
FileStream(stream=obj)
except ValidationError as e:
if "binary file-like" in str(e):
FileStream(stream=io.BytesIO(obj.read())) # only if read() exists Prevention
- Always buffer network streams with io.BytesIO before wrapping.
- Open local files in 'rb' mode.
When it happens
Trigger: Passing an httpx response .aread()-style stream, a websocket/generator payload, io.StringIO wrapped oddly, or a custom buffer without seek() to a field typed ValidatedBinaryIO / FileStream(stream=...).
Common situations: Streaming downloads handed straight to FileStream without buffering; network stream objects that only support sequential reads; text streams where the developer expected automatic transcoding.
Related errors
- Expected an async readable object with async read() method
- Cannot convert {type(value).__name__} to file source
- Cannot convert {type(v).__name__} to file source
- Missing required input '{name}'{suffix}
- Invalid input '{location}': {error.get('msg')}
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/ed248c678a6589fc.
Report an issue: GitHub.