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
- Send the file as multipart/form-data with a proper file part, not a JSON body.
- In tests, construct a real UploadFile or use httpx files=... with TestClient so the framework wraps the part.
- Align the route parameter type with the actual payload (use str/bytes + Form() if it's text, UploadFile only for files).
- 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
- Send files as multipart/form-data with a file part, never JSON.
- In tests use httpx/TestClient files=... so the framework wraps the part.
- Match the route parameter type to the payload (UploadFile for files, Form/str for text).
- Don't call UploadFile._validate directly with raw values.
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
- {"errors": exc.errors(), "body": body.decode()}
- {"errors": exc.errors(), "body": body.decode()}
- e.errors(include_url=False)
- Invalid ID format, it must start with "isbn-" or "imdb-"
- Invalid YAML
AI-assisted analysis of tiangolo/fastapi@42a41db11f (2026-08-04).
Data as JSON: /data/errors/8693ca626d9c6114.json.
Report an issue: GitHub.