crewAIInc/crewAI · error · ValueError

Cannot convert {type(value).__name__} to file source

Error message

Cannot convert {type(value).__name__} to file source

What it means

Raised by the _normalize_source BeforeValidator in sources.py: the value's type matches none of the supported coercions — str (http(s) -> FileUrl, else FilePath), Path -> FilePath, bytes -> FileBytes, AsyncReadable instance -> AsyncFileStream, or an object with read+seek -> FileStream. Any other type (int, dict, list, sync generator, arbitrary object) reaches the final raise.

Source

Thrown at lib/crewai-files/src/crewai_files/core/sources.py:578


def _normalize_source(value: Any) -> FileSource:
    """Convert raw input to appropriate source type."""
    if isinstance(value, (FilePath, FileBytes, FileStream, AsyncFileStream, FileUrl)):
        return value
    if isinstance(value, str):
        if value.startswith(("http://", "https://")):
            return FileUrl(url=value)
        return FilePath(path=Path(value))
    if isinstance(value, Path):
        return FilePath(path=value)
    if isinstance(value, bytes):
        return FileBytes(data=value)
    if isinstance(value, AsyncReadable):
        return AsyncFileStream(stream=value)
    if hasattr(value, "read") and hasattr(value, "seek"):
        return FileStream(stream=value)
    raise ValueError(f"Cannot convert {type(value).__name__} to file source")


RawFileInput = str | Path | bytes
FileSourceInput = Annotated[
    RawFileInput | FileSource, BeforeValidator(_normalize_source)
]

View on GitHub (pinned to 754d7323be)

Solutions

  1. Convert to a supported type first: bytes -> FileBytes, path str/Path -> FilePath, http(s) str -> FileUrl, binary file object -> FileStream.
  2. For dicts/JSON payloads, serialize to bytes: json.dumps(d).encode() then FileBytes.
  3. Ensure you import source classes from crewai_files.core.sources itself so isinstance coercion matches.

Example fix

# before
File(payload={"name": "x", "data": "..."})  # dict not supported

# after
import json
File(payload=FileBytes(data=json.dumps(payload).encode()))
Defensive patterns

Strategy: type-guard

Validate before calling

from pathlib import Path
from crewai_files.core.sources import AsyncReadable

def coercible(v) -> bool:
    return isinstance(v, (str, Path, bytes, AsyncReadable)) or (hasattr(v, "read") and hasattr(v, "seek"))

Type guard

from pathlib import Path
from crewai_files.core.sources import FileUrl, FilePath, FileBytes, AsyncFileStream

def to_source(v):
    if isinstance(v, str):
        return FileUrl(url=v) if v.startswith(("http://", "https://")) else FilePath(path=Path(v))
    if isinstance(v, Path):
        return FilePath(path=v)
    if isinstance(v, bytes):
        return FileBytes(data=v)
    if hasattr(v, "read") and hasattr(v, "seek"):
        return FileStream(stream=v)
    raise TypeError(f"unsupported source type {type(v).__name__}")

Try / catch

try:
    File(source=raw)
except ValidationError as e:
    if "to file source" in str(e):
        File(source=FileBytes(data=bytes(raw)))  # only when raw is bytes-like

Prevention

When it happens

Trigger: Passing an int, dict, or None where a file source is expected (model field typed FileSourceInput); a generator or iterator object; a text-mode-only wrapper without read+seek; passing FileUrl/FilePath before importing them so isinstance checks in this module miss a re-exported class.

Common situations: Dynamic payloads from APIs (JSON objects) fed straight into file-source fields; users assuming any iterable of bytes coerces; version skew where the FilePath class the caller imported comes from a different module identity than the one checked.

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/67d1006c2785faee. Report an issue: GitHub.