-
-
Notifications
You must be signed in to change notification settings - Fork 777
Open
Description
When registering multiple OpenAPI specs in a Connexion app, Connexion v3 raises a misleading error message about duplicate blueprint names. The error suggests a name conflict, but the actual root cause is unrelated.
Reproduction steps
- Define a JWT-protected API (openapi.yaml).
openapi: 3.0.0
info:
title: Simple API
version: 1.0.0
servers:
- url: http://localhost:8000
paths:
/hello:
get:
operationId: api.hello
security:
- bearerAuth: []
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
message:
type: string
options:
operationId: api.hello_options
responses:
'200':
description: CORS preflight
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
x-bearerInfoFunc: app.decode_token
- Add a separate small API for Kubernetes liveness/readiness checks (ping-api.yaml).
Load both APIs in the sameFlaskApp
(there's an intentional typo in the JWT token decode function, but Connexion will eventually raise a misleading"The name 'ping' is already registered for a different blueprint."
error, pointing to a different API and to a problem that does not actually exist):
import connexion
from connexion.exceptions import OAuthProblem
from flask_cors import CORS
def decode_jwt(token):
if token == "fake123":
return {"sub": "user123"}
raise OAuthProblem("Invalid token")
def ai_ping() -> str:
"""
ping function, for pod readiness/liveness probes
"""
return 'alive'
def main():
app = connexion.FlaskApp(__name__, specification_dir="./")
app.add_api("ping-api.yaml", name="ping", validate_responses=True, strict_validation=True)
app.add_api("openapi.yaml", name="hello", validate_responses=True, strict_validation=True)
CORS(app.app)
app.run(host="0.0.0.0", port=8000)
if __name__ == "__main__":
main()
- Test the liveness endpoint:
curl http://127.0.0.1:8000/ai-ping
Actual behavior
Connexion raises:
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/home/giulio/py/jwt-openapi/.venv/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 409, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "/home/giulio/py/jwt-openapi/.venv/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 60, in __call__
return await self.app(scope, receive, send)
File "/home/giulio/py/jwt-openapi/.venv/lib/python3.10/site-packages/connexion/middleware/main.py", line 501, in __call__
self.app, self.middleware_stack = self._build_middleware_stack()
File "/home/giulio/py/jwt-openapi/.venv/lib/python3.10/site-packages/connexion/middleware/main.py", line 338, in _build_middleware_stack
app.add_api(
File "/home/giulio/py/jwt-openapi/.venv/lib/python3.10/site-packages/connexion/apps/flask.py", line 147, in add_api
self.app.register_blueprint(api.blueprint, name=name)
File "/home/giulio/py/jwt-openapi/.venv/lib/python3.10/site-packages/flask/sansio/scaffold.py", line 47, in wrapper_func
return f(self, *args, **kwargs)
File "/home/giulio/py/jwt-openapi/.venv/lib/python3.10/site-packages/flask/sansio/app.py", line 595, in register_blueprint
blueprint.register(self, options)
File "/home/giulio/py/jwt-openapi/.venv/lib/python3.10/site-packages/flask/sansio/blueprints.py", line 310, in register
raise ValueError(
ValueError: The name 'ping' is already registered for a different blueprint. Use 'name=' to provide a unique name.
INFO: 127.0.0.1:38618 - "GET /ai-ping HTTP/1.1" 500 Internal Server Error
This error is misleading:
- There is no actual blueprint name collision.
- The failure has nothing to do with
name=
and not even with that endpoint.
Expected behavior
Connexion should raise a clear error message that reflects the real root cause, not a false duplicate-name conflict.
Notes
- Connexion v2 handled this correctly.
- Connexion v3 introduces this misleading error, making debugging extremely difficult.
- This issue is particularly problematic in Docker/Kubernetes environments where the behavior differs from local development due to missing files in the container build, making it even harder to identify the real root cause.
Metadata
Metadata
Assignees
Labels
No labels