fastapi: Duplicated OperationID when adding route with multiple methods

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

router.add_api_route(
    "/clear",
    clear,
    methods=["POST", "DELETE"]
)

Description

Seems to be caused by #4650.

The new generate_unique_id() function uses list(route.methods)[0].lower() as suffix for the operation_id. Therefore, in my example, both post and delete endpoints get _post suffix for operation_id, causing it to no longer be unique.

It then issues a “UserWarning: Duplicate Operation ID”

Operating System

Windows

Operating System Details

No response

FastAPI Version

0.75.0

Python Version

3.10.2

Additional Context

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 4
  • Comments: 17

Commits related to this issue

Most upvoted comments

Similar issue: UserWarning: Duplicate Operation ID

I’ve been reducing my example until all I have is this:

Freeze

fastapi==0.88.0 uvicorn==0.20.0 NOT using libs from global environment.

users.py

from fastapi import APIRouter

router = APIRouter()

@router.get("")
def users():
    return 1

__init__.py

# typical boilerplate

@app.get("/get_config")
def get_config():
    return cfg.properties

main.py

from <my_package> import app
...
app.include_router(users.router, prefix="/users", tags=["Users"])

With this, I get the warning:

[...].venv/lib/python3.10/site-packages/fastapi/openapi/utils.py:184: UserWarning: Duplicate Operation ID users_users_get for function users at [...]/<my_library>/routers/users.py
  warnings.warn(message)

Funny, though…

… when I take the endpoint from an app.route mount and paste it directly into __init__.py, like this:

app.get("/users")
def users():
    return 1

, just adjusting the endpoint, so that it is the same /users, no warning is issued!

What am I missing? Am I using app.include_router wrong? The API seems to work anyway, but some of us just don’t like warnings, because those make us think we’re not perfect.

@KRC1997 Yeah you’re right (in a way). I only add the router once, but the problem occurred when I started using asgi-lifespan to include the startup- and shutdown routines (the app lifecycle) of my app when running tests. I had my test_app fixture not session-scoped but test-scoped (default) so it was re-initializing the app (including startup routines) for each and every test. But of course the actual app: FastAPI object was only imported once, so the startup routine was applied to the same app instance for every test. Now when you add the routers in that very startup routine, it will be added every time.

The following workaround fixed the problem for me and also fixed another issue I had anyway: I now still initialize the database client in the startup routine (and close it in the shutdown routine) but everything that belongs to initializing the actual app instance (e.g. registering routers), I moved to a pre_startup routine/function that just runs whenever the app module is loaded (on import):

def pre_startup_routine(app: FastAPI) -> None:
    # add middlewares
    ...

    # register routers
    ...

async def startup_routine() -> None:
    # init database client
    ...

async def shutdown_routine() -> None:
    # close database client and cleanup
    ...

# create FastAPI app instance
app = FastAPI(
    # ...
    on_startup=[startup_routine],
    on_shutdown=[shutdown_routine],
)

pre_startup_routine(app)

This has the additional advantage that it works well with my test setup. If the reason for this warning is really only this mistake on the dev side, I guess this issue might also be closed as it’s not really an issue with FastAPI but rather with how the app’s lifecycle is handled in some situations.

Just a thought: Can you or anyone facing the issue, confirm if you have included the router (with all routes) only once in the parent router or the fastapi app? I was facing the same warning when I noticed I had added called app.include_router with the same router argument more than once. It resolved itself when I removed the extra call.

Hello @bneijt, I confirm I hit the same issue with fastapi@0.79.1. I’ve decorated a method like this:

@router.api_route(
    "/example",
    methods=["POST", "PUT"],
    status_code=status.HTTP_201_CREATED,
)
async def save_example(...)
  pass

No. @mbrav problem is unrelated to this.