Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class 'starlette.responses.JSONResponse'> is a valid pydantic field type #5861

Closed
9 tasks done
zadigus opened this issue Jan 9, 2023 · 18 comments
Labels
answered bug Something isn't working reviewed

Comments

@zadigus
Copy link

zadigus commented Jan 9, 2023

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google "How to X in FastAPI" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

import logging

from fastapi import APIRouter
from fastapi.responses import JSONResponse

liveness = True

router = APIRouter()


@router.get(
    "/livez",
    summary="Liveness probe",
    description="Returns 200 if the service is alive",
)
async def get_liveness() -> JSONResponse:
    logging.debug("GET /livez")
    if liveness:
        return JSONResponse(status_code=200, content={"status": "ok"})
    else:
        return JSONResponse(status_code=500, content={"status": "not ok"})

Description

With version 0.88.0, my unit tests run fine, I get no error. With version 0.89.0, I get the following error:

/root/.pyenv/versions/3.8/lib/python3.8/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1014: in _gcd_import
    ???
<frozen importlib._bootstrap>:991: in _find_and_load
    ???
<frozen importlib._bootstrap>:975: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:671: in _load_unlocked
    ???
/root/.pyenv/versions/3.8/lib/python3.8/site-packages/_pytest/assertion/rewrite.py:168: in exec_module
    exec(co, module.__dict__)
tests/models/conftest.py:7: in <module>
    from my_sample_lib.main import app
my_sample_lib/main.py:10: in <module>
    from my_sample_lib.health.router import router as health_router
my_sample_lib/health/router.py:24: in <module>
    async def get_liveness() -> JSONResponse:
/root/.pyenv/versions/3.8/lib/python3.8/site-packages/fastapi/routing.py:633: in decorator
    self.add_api_route(
/root/.pyenv/versions/3.8/lib/python3.8/site-packages/fastapi/routing.py:572: in add_api_route
    route = route_class(
/root/.pyenv/versions/3.8/lib/python3.8/site-packages/fastapi/routing.py:400: in __init__
    self.response_field = create_response_field(
/root/.pyenv/versions/3.8/lib/python3.8/site-packages/fastapi/utils.py:90: in create_response_field
    raise fastapi.exceptions.FastAPIError(
E   fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class 'starlette.responses.JSONResponse'> is a valid pydantic field type

The only way I found to get rid of the error is to remove the type hint, which I don't really want. Also, I tried to follow the guidelines provided in your documentation without success.

Interestingly, the whole thing works fine (with the type hint and fastapi 0.89.0) under Windows 10. Under Ubuntu 22.10, it doesn't work at all (i.e. it provides the above message).

Operating System

Linux

Operating System Details

Under Windows 10, it works like a charm. Under Ubuntu 22.10, it fails with the provided error above.

FastAPI Version

0.89.0

Python Version

3.8.12

Additional Context

It is also failing with python 3.9, and 3.10.

@zadigus zadigus added the question Question or problem label Jan 9, 2023
@ThirVondukr
Copy link

ThirVondukr commented Jan 9, 2023

I encountered the same error with response classes

@zadigus You can specify response_model manually but I'm not sure if that's correct here 🤔

@moadennagi
Copy link

moadennagi commented Jan 9, 2023

pydantic does not recognize JSONReponse as being a valid field type, pydantic documentation says to add arbitrary_types_allowed in the Config to allow for arbitrary user types: (https://docs.pydantic.dev/usage/model_config/)

whether to allow arbitrary user types for fields (they are validated simply by checking if the value is an instance of the type). If False, RuntimeError will be raised on model declaration (default: False). See an example in Field Types.

The issue happens in fastapi.utils.create_response_field which calls pydantic.fields.ModelField (partially), it passes down model_config=pydantic.config.BaseConfig as a default value.
Perhaps fastapi needs to add a way to pass custom config class when constructing the APIRoute to be passed down to create_response_field

class MyConfig:
    arbitrary_types_allowed = True

@ThirVondukr
Copy link

pydantic does not recognize JSONReponse as being a valid field type, pydantic documentation says to add arbitrary_types_allowed in the Config to allow for arbitrary user types: (https://docs.pydantic.dev/usage/model_config/)

whether to allow arbitrary user types for fields (they are validated simply by checking if the value is an instance of the type). If False, RuntimeError will be raised on model declaration (default: False). See an example in Field Types.

The issue happens in fastapi.utils.create_response_field which calls pydantic.fields.ModelField (partially), it passes down model_config=pydantic.config.BaseConfig as a default value. Perhaps fastapi needs to add a way to pass custom config class when constructing the APIRoute to be passed down to create_response_field

class MyConfig:
    arbitrary_types_allowed = True

I think adding arbitrary_types_allowed=True would only cause Response to be interpreted as

content: Any
status_code: int
headers: ...
...

(As in Response.__init__), and what would be preferred is either fastapi recognizing Response subclasses or mentioning it in documentation and recommending a workaround (for example passing response_model=None explicitly)

@novitae
Copy link

novitae commented Jan 9, 2023

Same issue here, it is only checking for instances of pydantic.fields.ModelField, and ignoring instances of starlette.responses.Response, where comes from JSONResponse ...

It is also failing with python 3.9, and 3.10.

And 3.11

@rassie
Copy link

rassie commented Jan 9, 2023

Pretty sure it's a regression in release 0.89, since its only new feature deals with response_models: #1436.

EDIT: Forgot to mention: my code worked with 0.88, but doesn't with 0.89, which is why I'm sure it's the culprit.

nsoranzo added a commit to galaxybot/galaxy that referenced this issue Jan 9, 2023
Fix the following traceback:

```
lib/galaxy/webapps/galaxy/fast_app.py:178: in initialize_fast_app
    add_galaxy_middleware(app, gx_app)
lib/galaxy/webapps/galaxy/fast_app.py:127: in add_galaxy_middleware
    async def preflight_handler(request: Request, rest_of_path: str) -> Response:
.venv/lib/python3.7/site-packages/fastapi/routing.py:658: in decorator
    generate_unique_id_function=generate_unique_id_function,
.venv/lib/python3.7/site-packages/fastapi/routing.py:598: in add_api_route
    generate_unique_id_function=current_generate_unique_id,
.venv/lib/python3.7/site-packages/fastapi/routing.py:401: in __init__
    name=response_name, type_=self.response_model
.venv/lib/python3.7/site-packages/fastapi/utils.py:92: in create_response_field
    ) from None
E   fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class 'starlette.responses.Response'> is a valid pydantic field type
```

tracked upstream in tiangolo/fastapi#5861 .
@iudeen
Copy link
Contributor

iudeen commented Jan 10, 2023

Looks like a regression. Try with 0.88 if the issue exist?

@rassie
Copy link

rassie commented Jan 10, 2023

Yes, 0.88 works as expected.

@hofrob
Copy link

hofrob commented Jan 10, 2023

Small script to reproduce:

  • python 3.11
  • FastAPI 0.89
from fastapi import FastAPI, Response


app = FastAPI(debug=True)


@app.get("/plain-text")
def plain_text() -> Response:
    return Response(content="bla", media_type="text/plain")

Running this with python main.py will show this error.

Traceback (most recent call last):
  File "../fastapi-regression/main.py", line 7, in <module>
    @app.get("/plain-text")
     ^^^^^^^^^^^^^^^^^^^^^^
  File "../fastapi-regression/venv/lib/python3.11/site-packages/fastapi/routing.py", line 633, in decorator
    self.add_api_route(
  File "../fastapi-regression/venv/lib/python3.11/site-packages/fastapi/routing.py", line 572, in add_api_route
    route = route_class(
            ^^^^^^^^^^^^
  File "../fastapi-regression/venv/lib/python3.11/site-packages/fastapi/routing.py", line 400, in __init__
    self.response_field = create_response_field(
                          ^^^^^^^^^^^^^^^^^^^^^^
  File "../fastapi-regression/venv/lib/python3.11/site-packages/fastapi/utils.py", line 90, in create_response_field
    raise fastapi.exceptions.FastAPIError(
fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class 'starlette.responses.Response'> is a valid pydantic field type

@rassie
Copy link

rassie commented Jan 10, 2023

@hofrob with a test case so small, you'd have to wonder why the tests haven't catched this before release.

@ThirVondukr
Copy link

This issue should be fixed by #5855

@hofrob
Copy link

hofrob commented Jan 10, 2023

@hofrob with a test case so small, you'd have to wonder why the tests haven't catched this before release.

I guess we're all invited to add tests and fixes to this project. 🤷

@moadennagi
Copy link

This issue should be fixed by #5855

The pr sets response_model=None for Response subclasses, I wonder if there is way to support subclasses of Response

@tiangolo
Copy link
Owner

Thanks for the report and discussion everyone! ☕

The simple use case of a single Response class is now supported in FastAPI 0.89.1 (just release) 🎉

And for the other use cases where you want to have more complex type annotations (e.g. unions, other types), you can use response_model=None.

There's a lot of new docs about it here: https://fastapi.tiangolo.com/tutorial/response-model/#other-return-type-annotations

Also, this is sort of a duplicate of #5857 (it's the same issue underneath).

@zadigus
Copy link
Author

zadigus commented Jan 14, 2023

Fastapi version 0.89.1 solves the issue in my codebase.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 6, 2023

Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs.

@lendoo73
Copy link

lendoo73 commented Aug 9, 2023

I have the same issue
To resolve this issue I found only one way:

  1. pip show fastapi: Version: 0.101.0
  2. pip uninstall fastapi
  3. Then I modified my requirements.txt from fastapi to fastapi==0.88
  4. pip install -r requirements.txt
  5. pip uninstall fastapi
  6. Then I modified my requirements.txt again from fastapi==0.88 to fastapi
  7. pip install -r requirements.txt

And now my server runs without error...

@CharlesPerrotMinotHCHB
Copy link

CharlesPerrotMinotHCHB commented Sep 27, 2023

I think we should open a new issue, but I am also reproducing, using fastapi 0.103.1, and migrating from pydantic v1 to pydantic v2 (2.4.1, tried with 2.2.1 as well)

@Kludex
Copy link
Sponsor Collaborator

Kludex commented Sep 27, 2023

I think we should open a new issue, but I am also reproducing, using fastapi 0.103.1, and migrating from pydantic v1 to pydantic v2 (2.4.1, tried with 2.2.1 as well)

Please create a discussion. This issue was solved.

Repository owner locked as resolved and limited conversation to collaborators Sep 27, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
answered bug Something isn't working reviewed
Projects
None yet
Development

No branches or pull requests