crewAIInc/crewAI · error · ValueError
Expected an async readable object with async read() method
Error message
Expected an async readable object with async read() method
What it means
Pydantic validator error from the AsyncReadable schema: a value passed where an async-readable source is expected is not an instance of AsyncReadable (the protocol exposing an async read() method). The validator is a strict isinstance check — duck-typed objects that merely define async read() are rejected, unlike the sync stream validator. Raised as ValueError during model validation, so it typically surfaces wrapped in pydantic.ValidationError.
Source
Thrown at lib/crewai-files/src/crewai_files/core/sources.py:57
class _AsyncReadableValidator:
"""Pydantic validator for AsyncReadable 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) -> AsyncReadable:
if isinstance(value, AsyncReadable):
return value
raise ValueError("Expected an async readable object with async read() method")
ValidatedAsyncReadable = Annotated[AsyncReadable, _AsyncReadableValidator()]
def _detect_content_type_from_bytes(data: bytes) -> str | None:
if data.startswith(b"\x89PNG\r\n\x1a\n"):
return "image/png"
if data.startswith(b"\xff\xd8\xff"):
return "image/jpeg"
if data.startswith(b"%PDF-"):
return "application/pdf"
try:
decoded = data.decode("utf-8")
except UnicodeDecodeError:
return None
View on GitHub (pinned to 754d7323be)
Solutions
- Wrap your object so it explicitly satisfies AsyncReadable (e.g. pass it through AsyncFileStream or implement the AsyncReadable protocol explicitly on your class).
- If the data is already materialized, pass bytes via FileBytes instead of an async stream.
- If it is a sync file-like object, use FileStream (which duck-types on read/seek).
Example fix
# before
async with aiofiles.open("x.pdf", "rb") as f:
src = AsyncFileStream(stream=f) # aiofiles handle is not AsyncReadable instance
# after
data = await f.read()
src = FileBytes(data=data) Defensive patterns
Strategy: type-guard
Validate before calling
from crewai_files.core.sources import AsyncReadable
def is_async_readable(v) -> bool:
return isinstance(v, AsyncReadable) Type guard
from crewai_files.core.sources import AsyncReadable, AsyncFileStream
def as_async_source(v):
if isinstance(v, AsyncReadable):
return AsyncFileStream(stream=v)
if hasattr(v, "read") and hasattr(v, "seek"):
return v # sync path; use FileStream
raise TypeError("unsupported source") Try / catch
try:
AsyncFileStream(stream=obj)
except ValidationError as e:
if "async readable" in str(e):
data = await obj.read() if hasattr(obj.read, "__await__") else None # fall back per API shape Prevention
- Prefer materialized bytes (FileBytes) unless you truly need streaming.
- Remember this validator is isinstance-strict, not duck-typed.
When it happens
Trigger: Passing an aiofiles file object, an httpx response, or a custom async stream to a field typed ValidatedAsyncReadable (e.g. AsyncFileStream(stream=...)) — anything that is async-readable but not literally an AsyncReadable instance.
Common situations: Users naturally try aiofiles.open(...) results or any object with async read(); because the check is isinstance-based rather than structural, these all fail even though they quack correctly.
Related errors
- Cannot convert {type(v).__name__} to file source
- Expected a binary file-like object with read() and seek()
- Cannot convert {type(value).__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/74a5903b7c0d79ce.
Report an issue: GitHub.