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
No response
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"]
1. Run the MCVE
No response
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/
Main
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too