Description
A msgpsec validation error is raised when annotating as data: dict[str, UploadFile]. This is because what we actually give msgspec is list of UploadFiles, but they have to converted into a dictionary before that. Also, I wasn't able to find any tests for these (maybe I missed them) which may mean this has never worked :D
URL to code causing the issue
No response
MCVE
from __future__ import annotations
from litestar import post
from litestar.datastructures import UploadFile
from litestar.enums import RequestEncodingType
from litestar.params import Body
from litestar.status_codes import HTTP_201_CREATED
from litestar.testing.helpers import create_test_client
@post(path="/")
async def upload_files_object(
data: dict[str, UploadFile] = Body(media_type=RequestEncodingType.MULTI_PART)
) -> list[str]:
return list(data.keys())
with create_test_client([upload_files_object]) as client:
files = [("files", ("filename", b"1")), ("files", ("another_filename", b"1"))]
response = client.post("/", files=files)
assert response.status_code == HTTP_201_CREATED
assert response.json() == ["filename", "another_filename"]
Steps to reproduce
Screenshots
No response
Logs
Traceback (most recent call last):
File "/home/guacs/open-source/litestar/litestar/_signature/model.py", line 93, in _deserializer
return default_deserializer(target_type, value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/guacs/open-source/litestar/litestar/serialization/msgspec_hooks.py", line 118, in default_deserializer
raise TypeError(f"Unsupported type: {type(value)!r}")
TypeError: Unsupported type: <class 'list'>
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/guacs/open-source/litestar/litestar/_signature/model.py", line 189, in parse_values_from_connection_kwargs
return convert(kwargs, cls, strict=False, dec_hook=deserializer, str_keys=True).to_dict()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
msgspec.ValidationError: Unsupported type: <class 'list'> - at `$.data[...]`
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/guacs/open-source/litestar/litestar/middleware/exceptions/middleware.py", line 191, in __call__
await self.app(scope, receive, send)
File "/home/guacs/open-source/litestar/litestar/routes/http.py", line 82, in handle
response = await self._get_response_for_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/guacs/open-source/litestar/litestar/routes/http.py", line 134, in _get_response_for_request
return await self._call_handler_function(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/guacs/open-source/litestar/litestar/routes/http.py", line 154, in _call_handler_function
response_data, cleanup_group = await self._get_response_data(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/guacs/open-source/litestar/litestar/routes/http.py", line 193, in _get_response_data
parsed_kwargs = route_handler.signature_model.parse_values_from_connection_kwargs(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/guacs/open-source/litestar/litestar/_signature/model.py", line 202, in parse_values_from_connection_kwargs
raise cls._create_exception(messages=messages, connection=connection) from e
litestar.exceptions.http_exceptions.ValidationException: 400: Validation failed for POST http://testserver.local/
Traceback (most recent call last):
File "/home/guacs/open-source/litestar/litestar/_signature/model.py", line 93, in _deserializer
return default_deserializer(target_type, value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/guacs/open-source/litestar/litestar/serialization/msgspec_hooks.py", line 118, in default_deserializer
raise TypeError(f"Unsupported type: {type(value)!r}")
TypeError: Unsupported type: <class 'list'>
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/guacs/open-source/litestar/litestar/_signature/model.py", line 189, in parse_values_from_connection_kwargs
return convert(kwargs, cls, strict=False, dec_hook=deserializer, str_keys=True).to_dict()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
msgspec.ValidationError: Unsupported type: <class 'list'> - at `$.data[...]`
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/guacs/open-source/litestar/litestar/middleware/exceptions/middleware.py", line 191, in __call__
await self.app(scope, receive, send)
File "/home/guacs/open-source/litestar/litestar/routes/http.py", line 82, in handle
response = await self._get_response_for_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/guacs/open-source/litestar/litestar/routes/http.py", line 134, in _get_response_for_request
return await self._call_handler_function(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/guacs/open-source/litestar/litestar/routes/http.py", line 154, in _call_handler_function
response_data, cleanup_group = await self._get_response_data(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/guacs/open-source/litestar/litestar/routes/http.py", line 193, in _get_response_data
parsed_kwargs = route_handler.signature_model.parse_values_from_connection_kwargs(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/guacs/open-source/litestar/litestar/_signature/model.py", line 202, in parse_values_from_connection_kwargs
raise cls._create_exception(messages=messages, connection=connection) from e
litestar.exceptions.http_exceptions.ValidationException: 400: Validation failed for POST http://testserver.local/
Litestar Version
Main
Platform
Description
A msgpsec validation error is raised when annotating as
data: dict[str, UploadFile]. This is because what we actually give msgspec is list ofUploadFiles, but they have to converted into a dictionary before that. Also, I wasn't able to find any tests for these (maybe I missed them) which may mean this has never worked :DURL to code causing the issue
No response
MCVE
Steps to reproduce
Screenshots
No response
Logs
Litestar Version
Main
Platform