Fastapi: [BUG] Error generating OpenAPI with generated scheme

Created on 19 Sep 2019  Â·  17Comments  Â·  Source: tiangolo/fastapi

Hello!

I apologize in advance for my "English"

When trying to see "swagger" when the server is running without "--reload" parameter, an error appears "Fetch error: Internal Server Error /openapi.json"

It appears only if the documentation contains generated schemes (for example, single parameter with embed=True (as in the example below), or OAuth2PasswordRequestForm dependency).

If you add the option “--reload” to the uvicorn server launch command, the error disappears.

Traceback:

ERROR: Exception in ASGI application
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 375, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/usr/local/lib/python3.7/site-packages/starlette/applications.py", line 133, in __call__
    await self.error_middleware(scope, receive, send)
  File "/usr/local/lib/python3.7/site-packages/starlette/middleware/errors.py", line 177, in __call__
    raise exc from None
  File "/usr/local/lib/python3.7/site-packages/starlette/middleware/errors.py", line 155, in __call__
    await self.app(scope, receive, _send)
  File "/usr/local/lib/python3.7/site-packages/starlette/middleware/cors.py", line 76, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/site-packages/starlette/middleware/cors.py", line 76, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/site-packages/starlette/exceptions.py", line 73, in __call__
    raise exc from None
  File "/usr/local/lib/python3.7/site-packages/starlette/exceptions.py", line 62, in __call__
    await self.app(scope, receive, sender)
  File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 590, in __call__
    await route(scope, receive, send)
  File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 208, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 41, in app
    response = await func(request)
  File "/usr/local/lib/python3.7/site-packages/fastapi/applications.py", line 88, in openapi
    return JSONResponse(self.openapi())
  File "/usr/local/lib/python3.7/site-packages/fastapi/applications.py", line 80, in openapi
    openapi_prefix=self.openapi_prefix,
  File "/usr/local/lib/python3.7/site-packages/fastapi/openapi/utils.py", line 264, in get_openapi
    flat_models=flat_models, model_name_map=model_name_map
  File "/usr/local/lib/python3.7/site-packages/fastapi/utils.py", line 45, in get_model_definitions
    model_name = model_name_map[model]
KeyError: <class 'Body_refresh_access_token_users_refresh_token_post'>

Endpoint view function:

@auth_routes.post(
    '/refresh_token',
    status_code=HTTP_200_OK,
    response_model=AuthTokens
)
def refresh_access_token(
        *,
        refresh_token: str = Body(..., title='Refresh token', embed=True)
):

Response model scheme:

class AuthTokens(BaseModel):
    access_token: str = Schema(..., title='authorization_token')
    token_type: str = 'bearer'
    refresh_token: str = Schema(..., title='refresh token')

Environment:
Docker: 19.03.2, build 6a30dfc
Docker-compose: 1.23.1, build b02f1306
Used docker image: python:3.7-alpine
Python: 3.7.4
FastAPI: 0.38.0

P.S.: I understand that perhaps the swagger is not needed in the production version, but the presence of “--reload” in the docker in any version of the image, except for the development version, in my opinion is bad.

Thank you in advance!

bug

All 17 comments

Could you post your response model code? (AuthTokens)

@zamiramir, yes of course. Added to issue description.

@i8enn it's a bit difficult to guess what might be happening in your use case without being able to run the code.

Please, check the tutorial and make sure that everything is working correctly for you: https://fastapi.tiangolo.com/tutorial/security/ . Follow it as is, and see if it works as expected, that should let you see if the error is related to your current environment.

If that doesn't help you find the issue, then please create a minimal self-contained app in a single script that shows the error. That way we can run it and check it.

@tiangolo, okay, thanks. I'm check this during this week and I will say about the results.

I can reproduce with a simple endpoint that following the tutorial

@router.post("/v1/login")
async def user_login(login_credential: OAuth2PasswordRequestForm = Depends()):
    pass

And same error:

KeyError: <class 'Body_user_login_api_user_v1_login_post'>

Also, simple case described in docs:

@app.post("/login/")
async def login(*, username: str = Form(...), password: str = Form(...)):
    return {"username": username}

I also tested with single param as well:

@app.post("/login/")
async def login(*, username: str = Form(...)):
    pass

However, the error happens when I start debugging with uvicon import:

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("api.server:app", host="0.0.0.0", port=8000, reload=True) # reload=False doesn't affect

Start will fail using module option:

python -m api.server

If I start the app using uvicorn from command line, with or without reload --reload, it does just fine:

uvicorn api.server:app --reload

This is quite frustrating, since I rely OpenAPI UI to debug some simple tests.

@tiangolo hello! I apologize for the late answer.

Unfortunately, now I have to work a lot on project with "Django" and the development of an application that is written using "FastAPI" is now suspended.

But how godlike it is - working with FastAPI... Thank you very much for this beautiful framework!

In turned out to be on simple examples that it could not be reproduced, and therefore I had to reproduce a more similar my real project application structure and launch mechanisms.

I created a repository so that can conveniently deploy it locally.
This is done in haste, so some things may seem unnecessary as part of a this small example

In my application, I redefined the "uvicorn" launch command (unfortunately, I can’t remember why now).

Perhaps it’s because of launch of the application using "click" and calling the application initialization function in command function.


By the way, it seems I found another bug related to the generation of the circuit (it does not find routes). While this is not accurate - tomorrow I will check again and talk about the results.

@xgenvn, hello! Thanks for your help!

The error corresponds to mine, but I received it in a completely different way and I could not reproduce your case. Take a look at this branch of the repository: maybe I'm doing something wrong?

The start is the command:
```
python -m app
````

@i8enn So your branch is trying to reproduce my case?
I'll check it out.

Updated:

  • Fail case:
python -m app runserver
  • Success cases:
uvicorn app.main:app
uvicorn app.main:app --reload

@xgenvn I do not quite understand you.

If I understand correctly for try reproduce run fail case with python -m app runserver, then your entry file (app.__main__.py) contains similary code:

if __name__ == '__main__':
    import uvicorn
    uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=False)

I also made a view similar to yours in this example:

I also tested with single param as well:

@app.post("/login/")
async def login(*, username: str = Form(...)):
   pass

Next step - run python -m app runserver command. I run this command in docker. Now she is without a runserver, but I also checked with her.

If I understand you correctly, the problem arises from the uvicorn import (which I did in app.__main__.py). But I could not get such an effect. May be problem in packages version?

I read a little your comment editing history in which you talked about debugging through VS Code, i and also decided this to check. I launched a debug with an app module in my example and everything works.

@i8enn
I didn't change any line before reproducing the issue. And I run directly the command from a terminal, not using docker. Also the issue seems happening for MacOS as well as Ubuntu.
Packages version:

Python: 3.7.6
FastAPI: 0.49
Uvicorn: 0.11.3

If I understand you correctly, the problem arises from the uvicorn import (which I did in app.__main__.py)

Yep, this is where I think it raises the issue. I need to import uvicorn to launch and debug. The launcher command for VSCode is python -m ... hence it's the same with the fail case I described above.

Perhaps my issue is not exactly the same to you, but it raises within uvicorn domain so I decided to post it here.

By fail case I meant the /docs endpoint is not working, and I got the same error with resolving model names.

Thanks for reporting back @i8enn !

I'm glad you enjoyed working with FastAPI.

If later you come back to this and want to check the issue again, then you could create a simple self-contained example that replicates the problem, that way I could give it a look.

But meanwhile, I think we can then just close this issue, right?


@xgenvn if you are having problems, please create a new issue with a small self-contained example replicating your problem, that will allow me (or anyone else) to help you find the cause.

@tiangolo, yes, let's close the issue and if I encounter it later again, I will complement it.

Thank you for participating in my problem.

@tiangolo This issue is present on API gateway. Locally, with or without --reload there is no issue, but when deployed on AWS, /docs is inaccessible. Endpoints work fine, and you can even open the /openapi.json file directly.

@theoturner your issue does not sound like it is related, can you please open a new issue with a reproduction?

I ran into this same issue with 0.62

@cochiseruhulessin please open a new issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tsdmrfth picture tsdmrfth  Â·  3Comments

laith43d picture laith43d  Â·  3Comments

RogerioDosSantos picture RogerioDosSantos  Â·  3Comments

devtud picture devtud  Â·  3Comments

kkinder picture kkinder  Â·  3Comments