Middleware : Exception caught where it souldn't
I encountered this issue that was hard to track down :
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/app/.venv/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py", line 403, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 60, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.11/site-packages/connexion/apps/abstract.py", line 288, in __call__
return await self.middleware(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.11/site-packages/connexion/middleware/main.py", line 501, in __call__
self.app, self.middleware_stack = self._build_middleware_stack()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.11/site-packages/connexion/middleware/main.py", line 338, in _build_middleware_stack
app.add_api(
File "/app/.venv/lib/python3.11/site-packages/connexion/apps/flask.py", line 149, in add_api
self.app.register_blueprint(api.blueprint)
File "/app/.venv/lib/python3.11/site-packages/flask/sansio/scaffold.py", line 47, in wrapper_func
return f(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.11/site-packages/flask/sansio/app.py", line 595, in register_blueprint
blueprint.register(self, options)
File "/app/.venv/lib/python3.11/site-packages/flask/sansio/blueprints.py", line 310, in register
raise ValueError(
ValueError: The name '/api' is already registered for a different blueprint. Use 'name=' to provide a unique name.
I think it comes down to the assignment not taking place because of an Exception raised and silently caught here (so self.middleware_stack stays None) :
https://github.com/spec-first/connexion/blob/a1c53db7a74d0fbbc22913faf70bc3d1c1b08ee2/connexion/middleware/main.py#L499
And I think that the error in question can be a KeyError here (debugger won't drill further down) :
https://github.com/spec-first/connexion/blob/a1c53db7a74d0fbbc22913faf70bc3d1c1b08ee2/connexion/middleware/security.py#L131
There most likely was an error in my configuration, however I filled an issue because the cause is hidden by an exception caught wrongly which causes the library to misbehave in a way that is nowhere linked to the root cause of the issue.
Here is the KeyError :
Exception has occurred: KeyError
'scheme'
File "/home/liteapp/adh6/api_server/.venv/lib/python3.11/site-packages/connexion/middleware/security.py", line 131, in __init__
self.add_paths()
File "/home/liteapp/adh6/api_server/.venv/lib/python3.11/site-packages/connexion/middleware/abstract.py", line 235, in add_api
api = self.api_cls(specification, next_app=self.app, **kwargs)
File "/home/liteapp/adh6/api_server/.venv/lib/python3.11/site-packages/connexion/middleware/main.py", line 338, in _build_middleware_stack
app.add_api(
File "/home/liteapp/adh6/api_server/.venv/lib/python3.11/site-packages/connexion/middleware/main.py", line 501, in __call__
self.app, self.middleware_stack = self._build_middleware_stack()
File "/home/liteapp/adh6/api_server/.venv/lib/python3.11/site-packages/connexion/apps/abstract.py", line 288, in __call__
return await self.middleware(scope, receive, send)
File "/home/liteapp/adh6/api_server/.venv/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 29, in __call__
return await self.app(scope, receive, send)
File "/home/liteapp/adh6/api_server/.venv/lib/python3.11/site-packages/uvicorn/lifespan/on.py", line 86, in main
await app(scope, self.receive, self.send)
File "/usr/local/lib/python3.11/asyncio/events.py", line 84, in _run
self._context.run(self._callback, *self._args)
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 1936, in _run_once
handle._run()
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 608, in run_forever
self._run_once()
File "/usr/local/lib/python3.11/asyncio/base_events.py", line 641, in run_until_complete
self.run_forever()
File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
File "/usr/local/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
File "/home/liteapp/adh6/api_server/.venv/lib/python3.11/site-packages/uvicorn/server.py", line 67, in run
return asyncio.run(self.serve(sockets=sockets))
File "/home/liteapp/adh6/api_server/.venv/lib/python3.11/site-packages/uvicorn/_subprocess.py", line 80, in subprocess_started
target(sockets=sockets)
File "/usr/local/lib/python3.11/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/usr/local/lib/python3.11/multiprocessing/process.py", line 314, in _bootstrap
self.run()
File "/usr/local/lib/python3.11/multiprocessing/spawn.py", line 135, in _main
return self._bootstrap(parent_sentinel)
File "/usr/local/lib/python3.11/multiprocessing/spawn.py", line 122, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "<string>", line 1, in <module>
KeyError: 'scheme'
(it is possible that some lines are off because it is running inside a docker environment and the debugger is outside)
Thank you for your time and contribution to the open source world 👍
Would you please extend this issue with a small self-contained code example - I guess it has to have a configuration error of some kind - to demonstrate the exception and broken assignment? That way I can also try to step thru the debugger and reproduce your finding.
It's especially important to post an openapi.yaml file. It appears from the error that your spec might define a security scheme that requires a custom security handler? That same KeyError also is reported in issue #2061 where the spec uses an "openIdConnect" security scheme. It appears to me that Connexion has a bug here, and I proposed a fix in the discussion on that issue. Please comment.
It appears this bug was fixed two months ago in PR https://github.com/spec-first/connexion/pull/1940, and the fix is not yet in any public release.
However I don't think this is really fixed: my similar issue persists even when installing from main, so I'm going to debug it asap...
I see from my debugging print that it passing here but it swallwos and hides the exeption
try:
function = deep_getattr(module, attr_path)
except AttributeError as attr_error:
if last_import_error:
raise last_import_error
else:
print("Giulio *** *** - raise AttributeError:", attr_error)
raise
return function
$ python app.py
`ConnexionMiddleware.run` is optimized for development. For production, run using a dedicated ASGI server.
INFO: Started server process [5465]
INFO: Waiting for application startup.
Giulio *** *** - get_function_from_name - function_name: api.hello
Giulio *** *** - get_function_from_name - function_name: api.hello_options
Giulio *** *** - get_function_from_name - function_name: api.hello
Giulio *** *** - get_function_from_name - function_name: api.hello_options
Giulio *** *** - get_function_from_name - function_name: api.hello
Giulio *** *** - get_function_from_name - function_name: api.hello_options
Giulio *** *** - get_function_from_name - function_name: api.hello
Giulio *** *** - get_function_from_name - function_name: api.hello_options
Giulio *** *** - get_function_from_name - function_name: api.hello
Giulio *** *** - get_function_from_name - function_name: app.decode_token
Giulio *** *** - raise AttributeError: module 'app' has no attribute 'decode_token'
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
@giuliohome Today I encountered similar issue. I figured out the issue, which is actually not related to latest changes of connexion for sure, I can't share the code part mine but I can share the ways I debugged my application where exactly I caught the root cause.
The steps as follows:
- I first added the additional traceback in the connexions line code, for me it is on the file as highlighted in below image.
- I added code something like as below
except ImportError as e:
msg = f'Cannot resolve operationId "{operation_id}"! Import error was "{str(e)}"'
print("****************************************************************")
print(traceback.format_exc())
-- INSERT --
I would recommend to add the traceback in line /app/.venv/lib/python3.11/site-packages/flask/sansio/blueprints.py as per the issue description to confirm either it is app issue at your end or the connexion side issue.
Of course I know very well what to do and indeed I have already found the bug - for sure on Connexion side (and in particular due to their vers. 3) - and sent a PR fix to the maintainers (related to the detailed issue I have also opened, where I explain all the steps). Since you missed it, I paste again the PR below (and the issue is linked inside it)
https://github.com/spec-first/connexion/pull/2082
P.S. I'm afraid this repo is no longer actively supported though