tiangolo/fastapi · error · ValueError

Expected UploadFile, received: {type(__input_value)}

Error message

Expected UploadFile, received: {type(__input_value)}

What it means

ValueError raised by UploadFile._validate at datastructures.py:135. UploadFile registers a Pydantic validator (__get_pydantic_core_schema__ -> with_info_plain_validator_function(cls._validate)); during request parsing it checks isinstance(__input_value, StarletteUploadFile) and raises ValueError(f'Expected UploadFile, received: {type(__input_value)}') if the value is not an UploadFile. This happens when something feeds a non-file value into a parameter typed as UploadFile.

Source

Thrown at fastapi/datastructures.py:135

        Any next read or write will be done from that position.

        To be awaitable, compatible with async, this is run in threadpool.
        """
        return await super().seek(offset)

    async def close(self) -> None:
        """
        Close the file.

        To be awaitable, compatible with async, this is run in threadpool.
        """
        return await super().close()

    @classmethod
    def _validate(cls, __input_value: Any, _: Any) -> "UploadFile":
        if not isinstance(__input_value, StarletteUploadFile):
            raise ValueError(f"Expected UploadFile, received: {type(__input_value)}")
        return cast(UploadFile, __input_value)

    @classmethod
    def __get_pydantic_json_schema__(
        cls, core_schema: Mapping[str, Any], handler: GetJsonSchemaHandler
    ) -> dict[str, Any]:
        return {"type": "string", "contentMediaType": "application/octet-stream"}

    @classmethod
    def __get_pydantic_core_schema__(
        cls, source: type[Any], handler: Callable[[Any], Mapping[str, Any]]
    ) -> Mapping[str, Any]:
        from ._compat.v2 import with_info_plain_validator_function

        return with_info_plain_validator_function(cls._validate)


class DefaultPlaceholder:

View on GitHub (pinned to 42a41db11f)

Solutions

  1. Send the file as multipart/form-data with a proper file part, not a JSON body.
  2. In tests, construct a real UploadFile or use httpx files=... with TestClient so the framework wraps the part.
  3. Align the route parameter type with the actual payload (use str/bytes + Form() if it's text, UploadFile only for files).
  4. If invoking _validate manually, pass a starlette.datastructures.UploadFile instance.

Example fix

# before
client.post('/uploadfile/', json={'file': 'hello'})
# after
client.post('/uploadfile/', files={'file': ('f.txt', b'hello', 'text/plain')})
Defensive patterns

Strategy: type-guard

Validate before calling

from starlette.datastructures import UploadFile
def coerce_upload(value):
    if isinstance(value, UploadFile):
        return value
    raise TypeError('pass a multipart file part, not JSON')

Type guard

from starlette.datastructures import UploadFile
import typing
def is_upload_file(v: typing.Any) -> typing.TypeGuard[UploadFile]:
    return isinstance(v, UploadFile)

Try / catch

from fastapi.datastructures import UploadFile
try:
    UploadFile._validate(value, None)
except ValueError as e:
    raise TypeError(f'wrap as UploadFile before sending: {e}') from e

Prevention

When it happens

Trigger: Calling code (often tests or internal serialization) that constructs/replays a request body and passes a plain str/bytes/dict where the schema expects an UploadFile; JSON body sent to a route declaring file: UploadFile; calling UploadFile._validate directly with a non-file; programmatic TestClient calls that bypass multipart framing.

Common situations: Unit tests passing a raw string instead of a file-like object to a dependency; sending application/json where multipart/form-data with a file part is required; replaying a cached request body that lost the UploadFile wrapper; mismatch between route signature (UploadFile) and client payload.

Related errors


AI-assisted analysis of tiangolo/fastapi@42a41db11f (2026-08-04). Data as JSON: /data/errors/8693ca626d9c6114.json. Report an issue: GitHub.